Skip to content

Commit dd56268

Browse files
authored
fix: expose with the /api prefix (#2037)
1 parent 8ca72ed commit dd56268

150 files changed

Lines changed: 1811 additions & 1545 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.devcontainer/docker-compose.yml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ services:
4545
# Overrides default command so things don't shut down after the process ends.
4646
command: sleep infinity
4747
ports:
48-
- 3000:3000
48+
- 3001:3000
4949

5050
db:
5151
hostname: db
@@ -185,5 +185,16 @@ services:
185185
ports:
186186
- "1080:1080"
187187

188+
nginx:
189+
image: nginx:1.25-alpine
190+
hostname: nginx
191+
depends_on:
192+
- core
193+
ports:
194+
- "3000:3000" # expose nginx on localhost:3000
195+
volumes:
196+
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
197+
restart: unless-stopped
198+
188199
volumes:
189200
postgres-data:

.devcontainer/nginx/nginx.conf

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# nginx.conf
2+
# This Nginx config listens on port 3000 and appends /api to the incoming request path,
3+
# then forwards it to the 'core' container on port 3000.
4+
# It also preserves important headers and supports WebSocket upgrades.
5+
6+
events {
7+
worker_connections 1024;
8+
}
9+
10+
http {
11+
# Basic proxy settings
12+
proxy_redirect off;
13+
proxy_buffering off;
14+
client_max_body_size 50m;
15+
16+
# Timeouts
17+
proxy_connect_timeout 5s;
18+
proxy_send_timeout 60s;
19+
proxy_read_timeout 60s;
20+
21+
# Forwarded headers
22+
map $http_upgrade $connection_upgrade {
23+
default upgrade;
24+
'' close;
25+
}
26+
27+
upstream core_upstream {
28+
server core:3000; # Docker DNS resolves the 'core' service name
29+
keepalive 32;
30+
}
31+
32+
server {
33+
listen 3000;
34+
server_name _;
35+
36+
# Health check endpoint
37+
location = /health {
38+
return 200 "ok (nginx)\n";
39+
add_header Content-Type text/plain;
40+
}
41+
42+
# Catch-all: append /api to request path and proxy to core
43+
# Example: GET /users -> proxied as /api/users
44+
location / {
45+
# Rewrite the path by inserting /api right after the leading slash
46+
# $request_uri includes path + args; we'll rewrite just the path and preserve query string
47+
set $new_path /api$uri;
48+
49+
# Proxy to core using the rewritten path; args preserved
50+
proxy_set_header Host $host;
51+
proxy_set_header X-Forwarded-Host $host;
52+
proxy_set_header X-Real-IP $remote_addr;
53+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
54+
proxy_set_header X-Forwarded-Proto $scheme;
55+
56+
# WebSocket support
57+
proxy_set_header Upgrade $http_upgrade;
58+
proxy_set_header Connection $connection_upgrade;
59+
60+
proxy_http_version 1.1;
61+
62+
# Use proxy_pass with a URI to keep our rewritten $new_path
63+
# We construct the full URI using the variable and keep query string via $is_args$args
64+
proxy_pass http://core_upstream$new_path$is_args$args;
65+
}
66+
}
67+
}

.dockerignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ test
88
tmp
99
**/test
1010
**/*.test.ts
11+
**/*.spec.ts
1112
types
1213
docker
1314
API Collections

.github/workflows/test.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ env:
5252
GEOLOCATION_API_HOST: http://localhost:12345
5353

5454
jobs:
55-
build-node:
55+
build-unit:
5656
runs-on: ubuntu-latest
5757

5858
# Service containers to run with `container-job`
@@ -127,8 +127,9 @@ jobs:
127127
run: yarn vitest
128128

129129
test-node:
130-
needs: build-node
131130
strategy:
131+
# NOTE: switch this on if you want to have the result of all the shards to fix more tests at once.
132+
# fail-fast: false
132133
matrix:
133134
shard: [1/4, 2/4, 3/4, 4/4]
134135
runs-on: ubuntu-latest

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
"@fastify/type-provider-typebox": "5.1.0",
6868
"@fastify/websocket": "11.0.2",
6969
"@graasp/etherpad-api": "2.1.1",
70-
"@graasp/sdk": "5.16.4",
70+
"@graasp/sdk": "5.16.5",
7171
"@rapideditor/country-coder": "5.4.0",
7272
"@sentry/node": "7.119.2",
7373
"@sentry/tracing": "7.120.3",

setup.node.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1+
import { config } from 'dotenv';
12
import 'reflect-metadata';
3+
4+
config({ path: '.env.test', override: true });

src/app.ts

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -41,30 +41,30 @@ export default async function (instance: FastifyInstance): Promise<void> {
4141

4242
// register some dependencies manually
4343
registerDependencies(instance.log);
44-
45-
await instance.register(fp(metaPlugin));
44+
await instance.register(metaPlugin);
4645

4746
await instance.register(fp(passportPlugin));
48-
// need to be defined before member and item for auth check
49-
50-
await instance.register(maintenancePlugin);
51-
52-
await instance.register(fp(authPlugin));
5347

54-
await instance.register(async (instance) => {
55-
// core API modules
56-
await instance
57-
// the websockets plugin must be registered before but in the same scope as the apis
58-
// otherwise tests somehow bypass mocking the authentication through jest.spyOn(app, 'verifyAuthentication')
59-
.register(fp(websocketsPlugin), {
60-
prefix: '/ws',
61-
redis: {
62-
channelName: 'graasp-realtime-updates',
63-
connection: REDIS_CONNECTION,
64-
},
65-
})
66-
.register(fp(MemberServiceApi))
67-
.register(fp(ItemServiceApi))
68-
.register(tagPlugin);
69-
});
48+
await instance.register(
49+
async (instance) => {
50+
// need to be defined before member and item for auth check
51+
await instance.register(fp(authPlugin));
52+
// core API modules
53+
await instance
54+
// the websockets plugin must be registered before but in the same scope as the apis
55+
// otherwise tests somehow bypass mocking the authentication through jest.spyOn(app, 'verifyAuthentication')
56+
.register(fp(websocketsPlugin), {
57+
prefix: '/ws',
58+
redis: {
59+
channelName: 'graasp-realtime-updates',
60+
connection: REDIS_CONNECTION,
61+
},
62+
})
63+
.register(fp(MemberServiceApi))
64+
.register(fp(ItemServiceApi))
65+
.register(tagPlugin)
66+
.register(maintenancePlugin);
67+
},
68+
{ prefix: '/api' },
69+
);
7070
}

src/langs/fr.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"GREETINGS": "Merci de vous être inscrit-e sur notre plateforme.",
33
"SIGN_UP_VERIFY_EMAIL": "Vérifiez votre e-mail en cliquant sur le bouton ci-dessous.",
44
"SIGN_UP_TEXT": "Complétez l'inscription et connectez-vous.",
5-
"IGNORE_EMAIL_IF_NOT_REQUESTED": "Si vous n'êtes pas l'auteur-e de cette action', vous pouvez ignorer cet e-mail.",
5+
"IGNORE_EMAIL_IF_NOT_REQUESTED": "Si vous n'êtes pas l'auteur-e de cette action, vous pouvez ignorer cet e-mail.",
66
"SIGN_IN_BUTTON_TEXT": "Se connecter",
77
"SIGN_UP_BUTTON_TEXT": "S'inscrire",
88
"SIGN_IN_TEXT": "Vous nous avez demandé un lien magique pour vous connecter rapidement. Le voici :",
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { faker } from '@faker-js/faker';
2+
import { describe, expect, it } from 'vitest';
23

34
import { TRANSLATIONS } from '../../langs/constants';
45
import enTranslations from '../../langs/en.json';

src/plugins/meta.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
9090
return 'OK' as const;
9191
});
9292

93-
fastify.get('/status', async (_, reply) => {
93+
fastify.get('/api/status', async (_, reply) => {
9494
const searchService = resolveDependency(SearchService);
9595
const api = new HealthyStatus().format();
9696
const database = (await getDBStatusCheck(fastify.log)).format();
@@ -110,7 +110,7 @@ const plugin: FastifyPluginAsyncTypebox = async (fastify) => {
110110
};
111111
});
112112

113-
fastify.get('/version', async (_, reply) => {
113+
fastify.get('/api/version', async (_, reply) => {
114114
// allow request cross origin
115115
reply.header('Access-Control-Allow-Origin', '*');
116116
return `${APP_VERSION} @ ${BUILD_TIMESTAMP}`;

0 commit comments

Comments
 (0)