I am creating a reverse proxy server in NestJs and I encountered an error while proxying a request.
'Error: write EPROTO 8005BB0501000000:error:0A000152:SSL routines:final_renegotiate:unsafe legacy renegotiation disabled:../deps/openssl/openssl/ssl/statem/extensions.c:908:\n\n at WriteWrap.onWriteComplete [as oncomplete] (node:internal/stream_base_commons:94:16)\n at WriteWrap.callbackTrampoline (node:internal/async_hooks:130:17)'
Did not quite understood this but seems an error with ssl files. Please help.
Thanks.
const options = {
target: `${protocol}://${host}`,
pathRewrite: {
'^/proxy/':''
},
changeOrigin: true,
onProxyReq: function (proxyReq,req,res) {
// add any headers if required.
},
onError(err, req, res) {
},
proxyTimeout: 60 * 1000,
onProxyRes(proxyRes, req, res){
}
}
createProxyMiddleware{options}
Related
My environment
front - windows, port 3000
backend - linux (ubuntu) in docker container, port 5000
Vue(front) tsconfig.json
export default defineConfig({
plugins: [vue(), vueJsx()],
resolve: {
alias: {
"#": fileURLToPath(new URL("./src", import.meta.url)),
},
},
server: {
host: true,
port: 3000,
proxy: {
"/api": {
target: "http://127.0.0.1:5000",
changeOrigin: true,
secure: false,
rewrite: (path) => path.replace(/^\/api/, ""),
},
},
},
});
front api call code
const response = await axios.post("http://127.0.0.1:5000/users/login?email=" + code);
backend(Nestjs) - main.ts
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableCors({
origin: 'http://localhost:3000',
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
credentials: true,
});
await app.listen(5000);
}
bootstrap();
I expect the api call to go to the backend, localhost:5000
but i get a 404 error
When I tried with postman, I got normal return, but when I sent the request using axios in Vue with the same request, I got 404 not found.
The most incomprehensible thing is that with the current settings, it was normally requested when developing in the past.
I don't know how to fix this
please help a lot
Repositories currently being edited: https://github.com/PracticeofEno/ft_transcendence
thanks
omg... I send POST message..
But api is GET Message
I have an application I've built using NextJS that is hosted on Netlify. The API is hosted on Heroku (it's a NestJS project running GraphQL)
In local development mode, I have no problem with any of my SSR pages. However, in production, I continually get 500 errors that produce the following logs in the Netlify functions panel:
ERROR ApolloError: request to https://api.paladindeck.com/graphql failed, reason: Client network socket disconnected before secure TLS connection was established
at new ApolloError (/var/task/node_modules/#apollo/client/errors/errors.cjs:34:28)
at /var/task/node_modules/#apollo/client/core/core.cjs:1598:19
at both (/var/task/node_modules/#apollo/client/utilities/utilities.cjs:986:53)
at /var/task/node_modules/#apollo/client/utilities/utilities.cjs:979:72
at new Promise (<anonymous>)
at Object.then (/var/task/node_modules/#apollo/client/utilities/utilities.cjs:979:24)
at Object.error (/var/task/node_modules/#apollo/client/utilities/utilities.cjs:987:49)
at notifySubscription (/var/task/node_modules/zen-observable/lib/Observable.js:140:18)
at onNotify (/var/task/node_modules/zen-observable/lib/Observable.js:179:3)
at SubscriptionObserver.error (/var/task/node_modules/zen-observable/lib/Observable.js:240:7) {
graphQLErrors: [],
clientErrors: [],
networkError: FetchError: request to https://api.paladindeck.com/graphql failed, reason: Client network socket disconnected before secure TLS connection was established
at ClientRequest.<anonymous> (/var/task/node_modules/next/dist/compiled/node-fetch/index.js:1:64142)
at ClientRequest.emit (events.js:412:35)
at ClientRequest.emit (domain.js:475:12)
at TLSSocket.socketErrorListener (_http_client.js:475:9)
at TLSSocket.emit (events.js:400:28)
at TLSSocket.emit (domain.js:475:12)
at emitErrorNT (internal/streams/destroy.js:106:8)
at emitErrorCloseNT (internal/streams/destroy.js:74:3)
at processTicksAndRejections (internal/process/task_queues.js:82:21) {
type: 'system',
errno: 'ECONNRESET',
code: 'ECONNRESET'
},
extraInfo: undefined
}
I have attached Sentry to the application and it's capturing some similar information:
http
POST https://api.paladindeck.com/graphql [[undefined]]
Info
09:15:05
console
ApolloError: request to https://api.paladindeck.com/graphql failed, reason: Client network socket disconnected before secure TLS connection was established
at new ApolloError (/var/task/node_modules/#apollo/client/errors/errors.cjs:34:28)
at /var/task/node_modules/#apollo/client/core/core.cjs:1598:19
at both (/var/task/node_modules/#apollo/client/utilities/utilities.cjs:986:53)
at /var/task/node_modules/#apollo/client/utilities/utilities.cjs:979:72
at new Promise (<anonymous>)
at Object.then (/var/task/node_modules/#apollo/client/utilities/utilities.cjs:979:24)
at Object.error (/var/task/node_modules/#apollo/client/utilities/utilities.cjs:987:49)
at notifySubscription (/var/task/node_modules/zen-observable/lib/Observable.js:140:18)
at onNotify (/var/task/node_modules/zen-observable/lib/Observable.js:179:3)
at SubscriptionObserver.error (/var/task/node_modules/zen-observable/lib/Observable.js:240:7) {
graphQLErrors: [],
clientErrors: [],
networkError: FetchError: request to https://api.paladindeck.com/graphql failed, reason: Client network socket disconnected before secure TLS connection was established
at ClientRequest.<anonymous> (/var/task/node_modules/next/dist/compiled/node-fetch/index.js:1:64142)
at ClientRequest.emit (events.js:412:35)
at ClientRequest.emit (domain.js:475:12)
at TLSSocket.socketErrorListener (_http_client.js:475:9)
at TLSSocket.emit (events.js:400:28)
at TLSSocket.emit (domain.js:475:12)
at emitErrorNT (internal/streams/destroy.js:106:8)
at emitErrorCloseNT (internal/streams/destroy.js:74:3)
at processTicksAndRejections (internal/process/task_queues.js:82:21) {
type: 'system',
errno: 'ECONNRESET',
code: 'ECONNRESET'
},
extraInfo: undefined
}
Error
09:15:06
console
[GET] /_next/data/hHiW6IT3wpykwmCV9Cdhe/collections/d45ebedf-d7f1-4208-bfbf-e7aa1af43bd3/e54b8945-6ed0-4094-8c54-fbd42e755e97.json?cardInCollectionId=e54b8945-6ed0-4094-8c54-fbd42e755e97&collectionId=d45ebedf-d7f1-4208-bfbf-e7aa1af43bd3 (SSR)
Info
09:15:06
All of the other pages (which do not use SSR, but query the API) work as expected.
I have looked at other similar issues but none of the solutions have helped thus far.
When I'm unable to find a solution to an issue like this I tend to think I'm doing something very stupid and not realizing it. So, it's entirely possible I'm just missing something so basic I'm not even thinking about it.
Whew... that took me a few days.
So, it turns out this wasn't a simple thing to diagnose (at least, not for me).
The short answer to my problem was: Don't pass the context headers from getServerSideProps to the Apollo client. For some reason, those headers, even with the authorization header being appended, were causing something to break.
Here's what I'm doing now:
// graphql-client.ts
export class GraphQLClient {
private readonly logger = new Logger(GraphQLClient.name);
get value(): ApolloClient<NormalizedCacheObject> {
if (!this._client) {
this._client = this.createClient();
}
if (this._client === undefined)
throw new Error(`Error when creating graphql client`);
return this._client;
}
constructor(
private readonly user?: User | null,
private _client?: ApolloClient<NormalizedCacheObject>,
) {}
private createClient(): ApolloClient<NormalizedCacheObject> {
const isSsrMode = typeof window === 'undefined';
const httpLink = createHttpLink({ uri: apolloConfig.uri });
const authLink = setContext(async (_, context) => {
let token: string | undefined;
if (context?.headers?.cookie) {
try {
token = getCookie(TOKEN_COOKIE_NAME, context.headers.cookie);
} catch (err) {
this.logger.error(err);
token = await this.user?.getIdToken();
}
} else {
token = await this.user?.getIdToken();
}
const headers = {
// HERE IS HOW I FIXED THINGS
// If this is SSR, DO NOT PASS THE REQUEST HEADERS.
// Just send along the authorization headers.
// The **correct** headers will be supplied by the `getServerSideProps` invocation of the query.
...(!isSsrMode ? context.headers : []),
authorization: token ? `Bearer ${token}` : ``,
};
return { headers };
});
return new ApolloClient({
link: authLink.concat(httpLink),
credentials: 'include',
cache: new InMemoryCache({
possibleTypes: generatedIntrospection.possibleTypes,
}),
ssrMode: isSsrMode,
});
}
}
// mypage.tsx
...
...
...
export const getServerSideProps: GetServerSideProps = async (context) => {
if (!isCardDetailsPageQueryType(context.query))
return {
props: {},
};
const logger = new Logger(
`${CardDetailsPage.name}_${getServerSideProps.name}`,
);
const client = new GraphQLClient();
const GET_CARD_DETAILS_QUERY = gql`
// query
`;
const results = await client.value.query({
query: GET_CARD_DETAILS_QUERY,
variables: { id: context.query.cardInCollectionId },
context: {
headers: {
...context.req.headers, // <-- just pass the context headers, the client will automatically append the authorization header
},
},
});
const GET_OTHER_PRINTINGS_BY_NAME_QUERY = gql`
// query
`;
const otherPrintingResults = await client.value.query({
query: GET_OTHER_PRINTINGS_BY_NAME_QUERY,
variables: {
name: results.data.cardsInCollection.card.name,
collectionId: context.query.collectionId,
},
context: {
headers: {
...context.req.headers, // <-- same as above
},
},
});
return {
props: {
cardsInCollection: results.data.cardsInCollection,
otherPrintings: otherPrintingResults.data.otherPrintings,
allCardsInCollection: otherPrintingResults.data.allCardsInCollection,
},
};
};
This might be a very specific issue for my specific use case, but I do hope someone, someday, finds this helpful.
Error ScreenShot
Post Request Code (Vuejs)
let PROXY = "http://localhost:8080/";
let URL = PROXY + "api/security/oauth/token?grant_type=client_credentials"
URL += `&client_id=${this.ID}`;
URL += `&client_secret=${this.SECRET}`;
try {
let res = await axios.post(URL, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
console.log(res);
}
catch(err) {
console.log(err);
}
Vue.config.js (Proxy Setting)
module.exports = {
devServer: {
proxy: {
'https://outpost.mapmyindia.com/': {
target: "http://localhost:8080/",
changeOrigin: true
}
}
},
transpileDependencies: [
'vuetify'
]
}
I was getting a CORS-related error initially so I used this proxy thing but even then I am getting this error. There are some questions posted on StackOverflow related to the proxy setting in vuejs to remove CORS errors but none of them could resolve this issue therefore I have posted this question.
This is not a CORS issue. The ressource hasn't been found. You have 404 status code.
https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
I'm running an Angular Universal application that is talking to an API. Now I'm trying to set up a proxy in the Universal server that proxies API requests to the actual API server:
server.use(['/api', '/sitemap.txt'], createProxyMiddleware({
target: process.env.API_URL,
onProxyReq: req => {
console.log('Using origin: ' + getOrigin(req.getHeaders()));
req.setHeader('origin', getOrigin(req.getHeaders()));
},
pathRewrite: {'^/api': ''}
}));
This works perfectly when running locally, but when running it on the server (Azure WebApp), it doesn't work. I can see the console log being called in the WebApp logs, but the resulting document is the Angular application with a message "page not found".
I'm totally out of ideas on where to look for solutions.
Edit:
I tried another proxy middleware and it does do the trick. This code works both locally and on Azure.
import * as proxy from 'express-http-proxy';
// ...
server.use(['/api', '/sitemap.txt'], proxy(process.env.API_URL, {
proxyPathResolver: req => {
let url: string = req.url;
if (url.startsWith('/api')) {
url = url.substr(4);
}
return url;
},
proxyReqOptDecorator(proxyReqOpts, srcReq) {
proxyReqOpts.headers['origin'] = getOrigin(proxyReqOpts.headers);
return proxyReqOpts;
}
}));
But it has some other limitations that make it unusable for our project, so I still need this resolved.
I have it working correctly now. This is the current setup:
server.use(
'/api',
createProxyMiddleware({
target: process.env.API_URL,
changeOrigin: true,
headers: {
Connection: 'keep-alive',
},
onProxyReq: (proxyReq, req, _res) => {
proxyReq.setHeader('origin', getOrigin(req.headers));
},
pathRewrite: {
'^/api': '',
},
})
);
So I added changeOrigin and the keep-alive header. I'm not sure which of the two resolved the issue, once I got it to work I never bothered to check it out. I suspect it's the header, though.
The code is on github
The following example API Proxying During development
gives an example of a proxyTable
// config/index.js
module.exports = {
// ...
dev: {
proxyTable: {
// proxy all requests starting with /api to jsonplaceholder
'/api': {
target: 'http://jsonplaceholder.typicode.com',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}
}
under which they say,
The above example will proxy the request /api/posts/1 to http://jsonplaceholder.typicode.com/posts/1.
but clearly posts/1 is missing from the example.
Or should the /posts/1 be in the proxyTable or in the .vue file using axios like this,
axios.get("api/posts/1")
so that a HTTP GET request which starts with api with proxy to http://jsonplaceholder.typicode.com and then append the rest of that url, which in this case is /posts/1 and so it actually proxies to http://jsonplaceholder.typicode.com/posts/1
Is this correct?
----------EDIT FROM HERE DOWN------------
In my own case
// config/index.js
module.exports = {
// ...
dev: {
proxyTable: {
// proxy all requests starting with /conn to http://localhost:8081
'/conn': {
target: 'http://localhost:8081',
changeOrigin: true,
pathRewrite: {
'^/conn': ''
}
}
}
}
}
and
axios.get("/conn/api.php?action=read")
should proxy to,
http://localhost:8081/api.php?action=read
But I get a console error,
GET http://localhost:8080/conn/api.php?action=read 504 (Gateway Timeout)
Thanks