Laravel Vapor projects won't connect to database - database

None of my Laravel projects deployed on Vapor will connect to my Vapor database. I get a SQLSTATE[HY000] [2002] error every time. To try to figure it out, I've created a fresh test project, in the same AWS region as my DB (in case that was the problem). I changed nothing in the default Laravel app except:
I installed Vapor CLI and Core via Composer
I added the DB to the vapor.yml file
I added a test route that queries the DB
on the Vapor dashboard, I changed APP_DEBUG=true to see the errors at my vanity URL
The Vapor dashboard shows that the project is connected to my database (vapor-db). Yet I still get a connection error. I tried deleting the default DB entries in the .env file. Still doesn't connect. The Vapor docs indicate the above is all I need to do for it to just work seamlessly, but I have been struggling with this for almost a week. Help!!
vapor.yml:
id: 17458
name: laravel82
environments:
    production:
        database: vapor-db
        memory: 1024
        cli-memory: 512
        runtime: php-7.4
        build:
            - 'COMPOSER_MIRROR_PATH_REPOS=1 composer install --no-dev'
            - 'php artisan event:cache'
            - 'npm ci && npm run prod && rm -rf node_modules'
    staging:
        database: vapor-db
        memory: 1024
        cli-memory: 512
        runtime: php-7.4
        build:
            - 'COMPOSER_MIRROR_PATH_REPOS=1 composer install'
            - 'php artisan event:cache'
            - 'npm ci && npm run dev && rm -rf node_modules'
routes/web.php:
Route::get('/', function () {
    return view('welcome');
});
Route::get('dbtest', function () {
    return \DB::table('images')->first();
});
result (staging):
https://moonlit-moscow-xdmsycwlxrhx.vapor-farm-b1.com/dbtest
Illuminate\Database\QueryException SQLSTATE[HY000] [2002] (SQL: select
* from `images` limit 1)

Related

Why: Uncaught (in promise) Error: Error serializing buffer at eval (logger.js?4ee8:900:1)

Why #logdna/logger raise this:
Uncaught (in promise) Error: Error serializing buffer
at eval (logger.js?4ee8:900:1)
Following docs: https://www.npmjs.com/package/#logdna/logger
Have this config:
const logdna = require('#logdna/logger')
const options = {
app: `tikex-fe-${process.env.NEXT_PUBLIC_ENVIRONMENT ?? 'local'}`,
level: 'debug', // set a default for when level is not provided in function calls
}
export const logger = logdna.createLogger(
'89ed69e8d2a4e79cb5593d40********',
options
)
And logging like this:
logger.log('startPaymentReq exist')
What is wrong?
yarn build raise no error
Or it it more worth to set up a backend log endpoint and send there the text message?!

Dockerized react socket.io client with nginx is connected but not emitting to reversed proxy uvicorn asgi server (client to server and vice versa)

I have a dockerized react-uvicorn asgi app running on reversed proxy nginx.
When i run 'docker compose up --build' everything is connected and on page reload reconnecting is successful. The problem is that react can't emitt events or uvicorn is not recieving them.
The app was tested successfully without nginx locally and everything was ok until i added nginx and deployed on digitalocean.
I'm having some sleepless nights trying to figure it out and still don't know what the problem is. Can someone pls help me...
root directory hirarchy:
App
|__client(react)
| |__conf
| |__conf.d
| |__default.conf
| |__gzip.conf
| |__Dockerfile
| |__public
| |__src
| |__withSocket.tsx
| |__App.tsx
|__server(uvicorn)
| |__server.py
| |__Dockerfile
|__another-service(python socket.io)
| |__main.py
|__docker-compose.yml
docker-compose.yml
version: '3.9'
services:
api:
build: server/
restart: unless-stopped
volumes:
- ./server:/app
ports:
- 8080:8080
client:
build: ./newclient
restart: unless-stopped
ports:
- 80:80
another-service:
build: ./another-service
restart: unless-stopped
volumes:
- ./another-service:/app
ports:
- 5004:5004
depends_on:
- api
uvicorn asgi server.py
import socketio
import asyncio
import json
sio = socketio.AsyncServer(
async_mode='asgi',
async_handlers=True,
cors_allowed_origins="*",
logger=True,
engineio_logger=True,
always_connect=True,
ping_timeout=60
)
app = socketio.ASGIApp(sio, socketio_path='/socket.io')
#sio.event
async def connect(sid, environ, auth=None):
print(Fore.GREEN + 'connected ', sid)
#sio.event
def disconnect(sid):
print('disconnect ', sid)
#sio.on('example-event')
async def auth(sid, data):
data = json.loads(data)
print('received data: ' + data['data'])
if await client.is_user_authorized():
response = {
'auth_log': 'Authenticated',
'logged_in': True
}
await sio.emit('auth', response)
if __name__ == '__main__':
import uvicorn
uvicorn.run("server:app", host='0.0.0.0', port=8080, log_level="info")
uvicorn server Dockerfile
FROM python:3.9
ENV PYTHONUNBUFFERED 1
WORKDIR /app
COPY requirements.txt /app/requirements.txt
RUN pip install -r requirements.txt
RUN pip freeze > requirements.txt
COPY . /app
EXPOSE 8080
CMD python server.py
client React socket.io component-wrapper withSocket.tsx
import React from "react";
import { io, Socket } from "socket.io-client";
interface ServerToClientEvents {
auth: (data: any) => void
}
interface ClientToServerEvents {
connect: (connected: string) => void
example-event: (data: any) => void
}
// component wrapper that allows to use socket globally
function withSocket (WrappedComponent: any) {
const socket: Socket<ServerToClientEvents, ClientToServerEvents> = io(process.env.REACT_APP_SOCKET_URL!, {
transports: ["websocket"],
path: "/socket.io"
});
const WithSocket = (props: any) => {
// function to subscribe to events
const socketListen = async (queue: any, callback: any) => {
await socket.on(queue, (data?: any) => {
callback(data)
})
await socket.on('disconnect', () => socket.off());
}
const socketSend = async (queue?: any, data?: any) => {
await socket.emit(queue!, JSON.stringify(data))
}
return (
<WrappedComponent
{...props}
socketSend={socketSend}
socketListen={socketListen}
/>
)
}
return WithSocket
}
export default withSocket
client socket.io component App.tsx
import React, {useState, useEffect} from 'react'
import withSocket from "../withSocket";
import "./AuthForm.css"
function AuthForm({socketListen, socketSend}: { socketListen: any; socketSend: any }) {
const [data, setData] = useState('');
const [message, setMessage] = useState('');
useEffect(() => {
socketListen('auth', (data: any) => {
setMessage(JSON.stringify(data.auth_log))
})
}, [socketListen])
let handleSubmitData = async (e: any) => {
e.preventDefault();
try {
socketSend('example-event', {'data': data})
} catch (err) {
console.log(err);
}
}
return(
<>
<div className="form-wrapper">
<form onSubmit={handleSubmitData}>
<label>
<input type="text" name="data" placeholder="Data" onChange={(e) => setData(e.target.value)}/>
</label>
<button type="submit">Send</button>
</form>
<div className="message">
{message ? <p>{message}</p> : null}
</div>
</div>
</>
)
}
export default withSocket(AuthForm)
client .env file
REACT_APP_SOCKET_URL=ws://example-site.com
client react & nginx Dockerfile
# build environment
FROM node:alpine as builder
WORKDIR /app
COPY package.json .
COPY yarn.lock .
RUN yarn
COPY . .
RUN yarn build
# production environment
FROM nginx:1.15.2-alpine
RUN rm -rf /etc/nginx/conf.d
COPY conf /etc/nginx
COPY --from=builder /app/build /usr/share/nginx/html
EXPOSE 80
# Copy .env file and shell script to container
WORKDIR /usr/share/nginx/html
COPY ./env.sh .
COPY .env .
# Add bash
RUN apk add --no-cache bash
# Make our shell script executable
RUN chmod +x env.sh
# Start Nginx server
CMD ["/bin/bash", "-c", "/usr/share/nginx/html/env.sh && nginx -g \"daemon off;\""]
nginx configuration default.conf
# Use site-specific access and error logs and don't log 2xx or 3xx status codes
map $status $loggable {
~^[23] 0;
default 1;
}
access_log /var/log/nginx/access.log combined buffer=512k flush=1m if=$loggable;
error_log /var/log/nginx/error.log;
upstream socket-server-upstream {
server api:8080;
keepalive 16;
}
server {
listen 80;
listen [::]:80;
server_name example-site.com www.example-site.com;
client_max_body_size 15M;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
# enable WebSockets
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
expires -1;
}
location /socket.io {
proxy_pass http://socket-server-upstream/socket.io;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers *;
proxy_redirect off;
proxy_buffering off;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
nginx MIME-Type configuration gzip.conf
gzip on;
gzip_http_version 1.0;
gzip_comp_level 5; # 1-9
gzip_min_length 256;
gzip_proxied any;
gzip_vary on;
# MIME-types
gzip_types
application/atom+xml
application/javascript
application/json
application/rss+xml
application/vnd.ms-fontobject
application/x-font-ttf
application/x-web-app-manifest+json
application/xhtml+xml
application/xml
font/opentype
image/svg+xml
image/x-icon
text/css
text/plain
text/x-component;
As i already wrote at the beginning, the code is working locally without nginx and client is emitting events and the uvicorn server is recieving and emitting regularly. With nginx deployed on Ubuntu Server the services are also connected but client is not emitting. Why?
When you have 2 Docker containers (1 "frontend" container and 1 "backend" container) and they need to exchange information via HTTP or WebSocket then make sure that your domain points to your "backend" container e.g. api.your-domain.com (and call api.your-domain.com from your "frontend" container because you're reaching your API service from your browser).
If you have two "backend" containers like in your docker-comopose.yml file api and another-service and need to exchange information then make sure both services are on the same docker network. Take a look here: https://docs.docker.com/compose/networking/#specify-custom-networks
If they are on the same network then they can call each other by their service name e.g. another-service makes an API call over http://api:8080
(see here: https://stackoverflow.com/a/66588432/5734066)

Missing Patch method with corsheaders only on chrome

I have a Django app that's using corsheaders package and its in settings.py like this:
INSTALLED_APPS = [ ..., corsheaders, ...]
...
MIDDLEWARE = [
    # on top
    "corsheaders.middleware.CorsMiddleware",
    "django.middleware.common.CommonMiddleware",
    ...
]
...
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_CREDENTIALS = True
When I'm trying to do a PATCH request on Google Chrome after the OPTIONS method I get this:
The Access-Control-Allow-Methods is missing PATCHand the next request fails with CORS methods error.
But I tried the same method on Firefox and its working as intended.
Seems like you need to set allowed origins explicitly, not by using the wildcard i.e. *:
CORS_ALLOWED_ORIGINS = [
"https://example.com",
"https://sub.example.com",
"http://localhost:8080",
"http://127.0.0.1:9000"
]
Also, set all HTTP verbs:
CORS_ALLOW_METHODS = [
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
]
Read more:
https://pypi.org/project/django-cors-headers/
Chrome Cross-Domain PATCH request not working
CORS_ALLOW_ALL_ORIGINS = True or CORS_ORIGIN_ALLOW_ALL = True (OLD name) is equal to using wildcard * : L131 django-cors-headers middleware.py file

react test import deeply nested components

I have a React app. The folders looks like this:
├── src
│   ├── App.jsx
│   └── components
│      ├── charts
│      │   ├── Chart.jsx
│      └── editor
│         └── Editor.jsx
│
├── test
│   └── testComponents
│ ├── testCharts
│ │ └── testChart.js
│   └── testEditor
│   └── testEditor.js
│
├── package.json
└── webpack.config.js
Because the folders are deep, the import inside testChart.js looks like:
import Chart from './../../../src/components/charts/Chart.jsx'
// ...codes...
The ./../../../src/ ... is not very friendly I think. Is there any way to make it more clean like import charts/Charts.jsx?
Thanks for your time!
Based on the accepted answer, to be more clear:
// webpack.config.js
// ...
var path = require('path')
module.exports = {
// ...
resolve: {
alias: {
srcDir: path.resolve(__dirname, 'src/')
}
}
}
Then in testChart.js, you could directly import srcDir as following.
import Chart from 'srcDir/components/charts/Chart.jsx'
Give alias to Component files in webpack
https://webpack.js.org/configuration/resolve/

Issue importing Typescript in Angular CLI

I rewrote (wrapped) a js library to be a TypeScript one (tsroll). The purpose of this library is to roll dice. I am trying to use this in my Angular2 CLI applia
I installed it successfully (it now appears in my node_modules). I added it to the angular-cli-build.js file:
module.exports = function(defaults) {
return new Angular2App(defaults, {
vendorNpmFiles: [
'systemjs/dist/system-polyfills.js',
'systemjs/dist/system.src.js',
'zone.js/dist/*.js',
'es6-shim/es6-shim.js',
'reflect-metadata/*.js',
'rxjs/**/*.js',
'#angular/**/*.js',
'tsroll/dist/tsroll.js'
]
});
};
I also added the resulting vendor folder to my src/system-config.ts file:
// Apply the CLI SystemJS configuration.
System.config({
map: {
'#angular': 'vendor/#angular',
'rxjs': 'vendor/rxjs',
'main': 'main.js',
'tsroll': 'vendor/tsroll/dist'
},
packages: cliSystemConfigPackages
});
I also import it into my die-roller.component.ts file:
import { Component, OnInit } from '#angular/core';
import * as tsroll from 'tsroll/tsroll';
#Component({
moduleId: module.id,
selector: 'die-roller-app',
templateUrl: 'die-roller.component.html',
styleUrls: ['die-roller.component.css']
})
export class DieRollerComponent implements OnInit {
numberOf: number;
sides = [2, 4, 6, 8, 10, 12, 20, 100];
selectedSide: number;
constructor() {}
ngOnInit() {
this.numberOf = 1;
this.selectedSide = 20;
}
onSubmit(event) {
console.log(this.numberOf);
console.log(this.sides);
console.log(this.selectedSide);
// this line give me probs
var dr = new tsroll.DiceRoller.Droll();
}
}
Which gives me the following error:
zone.js:101 GET http://localhost:4200/vendor/tsroll/dist/tsroll 404 (Not Found)scheduleTask # zone.js:101ZoneDelegate.scheduleTask # zone.js:336Zone.scheduleMacroTask # zone.js:273(anonymous function) # zone.js:122send # VM20162:3fetchTextFromURL # system.src.js:1154(anonymous function) # system.src.js:1735ZoneAwarePromise # zone.js:584(anonymous function) # system.src.js:1734(anonymous function) # system.src.js:2759(anonymous function) # system.src.js:3333(anonymous function) # system.src.js:3600(anonymous function) # system.src.js:3985(anonymous function) # system.src.js:4448(anonymous function) # system.src.js:4700(anonymous function) # system.src.js:406ZoneDelegate.invoke # zone.js:323Zone.run # zone.js:216(anonymous function) # zone.js:571ZoneDelegate.invokeTask # zone.js:356Zone.runTask # zone.js:256drainMicroTaskQueue # zone.js:474ZoneTask.invoke # zone.js:426
zone.js:461 Unhandled Promise rejection: Error: XHR error (404 Not Found) loading http://localhost:4200/vendor/tsroll/dist/tsroll
at XMLHttpRequest.wrapFn [as _onreadystatechange] (http://localhost:4200/vendor/zone.js/dist/zone.js:769:30)
at ZoneDelegate.invokeTask (http://localhost:4200/vendor/zone.js/dist/zone.js:356:38)
at Zone.runTask (http://localhost:4200/vendor/zone.js/dist/zone.js:256:48)
at XMLHttpRequest.ZoneTask.invoke (http://localhost:4200/vendor/zone.js/dist/zone.js:423:34)
Error loading http://localhost:4200/vendor/tsroll/dist/tsroll as "tsroll/tsroll" from http://localhost:4200/app/die-roller/die-roller.component.js ; Zone: <root> ; Task: Promise.then ; Value: Error: Error: XHR error (404 Not Found) loading http://localhost:4200/vendor/tsroll/dist/tsroll(…)consoleError # zone.js:461_loop_1 # zone.js:490drainMicroTaskQueue # zone.js:494ZoneTask.invoke # zone.js:426
zone.js:463 Error: Uncaught (in promise): Error: Error: XHR error (404 Not Found) loading http://localhost:4200/vendor/tsroll/dist/tsroll(…)
How do I import my own/borrowed TypeScript into an Angular2 CLI Project?
I pasted what I thought was relevant code in here, but the full code can be found:
https://github.com/jdell64/testCli
I think that an entry is missing in the packages block for your tsroll libary, as described below:
System.config({
(...)
packages: {
tsroll: {
defaultExtension: 'js'
}
}
});

Resources