I'm proxying requests to an external backend from a Nextjs app and trying to extract an
Authorization header from the response using the native fetch library. However the headers in the fetch response are empty even though they are present in the actual response from the server.
Here's the setup in the next.config.js file:
module.exports = {
async headers() {
return [
{
source: '/api/:path*',
headers: [
{
key: 'Access-Control-Expose-Headers',
value: '*, authorization',
},
],
},
]
},
async rewrites() {
return [
{
source: '/api/:path*',
destination: `${process.env.NEXT_PUBLIC_BASE_URL}/api/:path*`,
},
]
},
}
With my limited knowledge of proxies I'm assuming that it's a reverse proxy and the headers are lost in the response back somewhere inside it.
I've also tried adding a middleware to try to localize where the headers are being lost without any luck.
Does anyone know where I can configure the headers to be included back from the proxy?
Thanks in advance! :)
I am reusing a fetcher from react-native and it seems like the method for extracting headers differs. 😅
This works using fetch in the browser:
response.headers.get('authorization')
In react-native: response.headers.map['authorization']
Related
I am trying to configure a proxy for my API requests using http-proxy-middleware, which the create react app docs suggest. I set up my proxy like this, in the setupProxy.js file:
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function (app) {
app.use(
createProxyMiddleware("/post", {
target: 'https://postman-echo.com',
changeOrigin: true,
logLevel: 'debug'
})
);
};
then, I do a simple POST to an endpoint:
const response = await fetch("/post", {
method: 'POST',
headers: {
'content-type': 'application/json;charset=UTF-8'
},
body: JSON.stringify({ foo1: "bar1", foo2: "bar2" })
});
console.log(await response.json());
According to the http-proxy-middleware docs, I should expect a proxy that does something like this:
[HPM] POST /post -> https://postman-echo.com/post
But instead, the debugger shows this:
[HPM] POST /post -> https://postman-echo.com
The path, /post, does not get appended to the proxy request. The target should actually be https://postman-echo.com/post. My client gets a 404 error because https://postman-echo.com on its own does not match anything on the backend.
If it did reroute correctly, I should expect the same results as a CURL request
curl -X POST -F 'foo1=bar1' -F 'foo2=bar2' https://postman-echo.com/post
{"args":{},"data":{},"files":{},"form":{"foo1":"bar1","foo2":"bar2"},"headers":{"x-forwarded-proto":"https","x-forwarded-port":"443","host":"postman-echo.com","x-amzn-trace-id":"Root=1-61200c54-7b5809be3e78040f09edcd42","content-length":"240","user-agent":"curl/7.64.1","accept":"*/*","content-type":"multipart/form-data; boundary=------------------------bb54b419e41f4a4a"},"json":null,"url":"https://postman-echo.com/post"}%
But I 404 because the path is not added. Why is the path being left out?
I created a simple app that recreates my issue. This looks similar to this issue but they are not the same (I am using the same syntax as the answer suggests).
I got it working. The problem was that I was testing with an endpoint that 404'd. I got confused because the debugger doesn't append /post to the end of the log like the docs say it should.
I am using Nuxt.js first time now. However I struggle with using the axios module of it somewhat. I like the fact that I can configure the baseUrl in the nuxt.config.js file. I expect. So this is what I did:
// nuxt.config.js
...
axios: {
baseUrl: 'http://localhost:3001',
publicRuntimeConfig: {
axios: {
browserBaseURL: "http://localhost:3004"
}
},
privateRuntimeConfig: {
axios: {
baseURL: "http://localhost:3005"
}
},
},
modules: [
'#nuxtjs/axios',
'#nuxtjs/auth-next',
'#nuxtjs/proxy'
],
...
Here comes my vue components method I declared to use the Nuxt.js axios module (using this.$axios.$get insteand of this.$axios.get). However I am not sure if there is a difference using this.$axios and just $axios. the latter is called a "plugin" according to the documentation. I did not manage to get axios working with only calling $axios - it can't be resolved so I stick with this.$axios.
Anyway here is method code containing the axios get call. As you can see I am omitting the base url https://localhost since I expect it to be prepended through the nuxt.config.js configuration.
updateTeams: function () {
this.$axios.$get('/api/teams')
.then(({data}) => {
this.teams = data
}).catch((error) => {
console.error(error)
})
}
The result is disappointing. The call is still done with http://localhost:3000 instead of one of the others I configured in the nuxt.config.js file. I rechecked the documentation twice but could not find any hint what I am doing wrong.
Request URL: http://localhost:3000/api/teams
So I have 2 applications:
an Adonis API server accessible via http://10.10.120.4:3333
A SSR app using Nuxt.js accessible via http://10.10.120.4:80
The Nuxt.js app is accessible outside using url http://my-website.com. I have axios module with this config
axios: {
baseURL: '0.0.0.0:3333/api',
timeout: 5000
}
Now the problem is, when I am requesting data with asyncData it works, but when the request was made from outside asyncData, say created() for example, it throws an error saying the url http:0.0.0.0:3333 is missing which is true since it's already running in the browser and not in the server.
The first solution that I've tried is to change the baseURL of the axios module to this
axios: {
baseURL: 'http://my-website.com/api',
timeout: 5000
}
But it seems nuxt server can't find it, so I think the solution is to make proxy and installed #nuxtjs/proxy.
And this is my proxy config in nuxt.config.js
{
proxy: {
'/api': 'http://my-website.com:3333',
}
}
and then I just changed my axios baseURL to
http://my-website.com/api
But again it didn't work.
My question is, how do you deal with this kind of scenario? Accessing different server from browser?
When using Proxy in a nuxt project you need to remove baseUrl and set proxy to true as seen below.
axios: {
// Do away with the baseUrl when using proxy
proxy: true
},
proxy: {
// Simple proxy
"/api/": {
target: "https://test.com/",
pathRewrite: { "^/api/": "" }
}
},
when making a call to your endpoint do:
// append /api/ to your endpoints
const data = await $axios.$get('/api/users');
checkout Shealan article
I currently have a Firebase App that works locally when I use localhost:5001 for calling the functions; however, when I try to use the cloud functions when directly routed I get ERROR: FORBIDDEN, and when I try to directly fetch from my deployed Firebase app I get a CORS error.
The front end calls a service, which fetches from the backend the data.
const requestOptions = {
method: 'GET',
mode: 'cors',
headers: new Headers({ 'Content-Type': 'application/json' })
};
return fetch("https://us-central1-polling-269dc.cloudfunctions.net/api/polls/get", requestOptions).then(handleResponse);
I've also tried just not having the mode and headers on there, but it doesn't work. Fetch is correctly being called, but on the loading page of https://polling-269dc.firebaseapp.com/#/ I get this error message:
Access to fetch at 'https://us-central1-polling-269dc.cloudfunctions.net/api/polls/get' from origin 'https://polling-269dc.firebaseapp.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
In my functions folder in my index.js, this is the function and prequisite imports:
const functions = require('firebase-functions');
const express = require('express');
const app = express();
const fire = require("./fire.js");
var database = fire.database();
var auth = fire.auth();
app.get("api/polls/get/", (req, res) => {
var ref = database.ref("polls/");
var query = ref.orderByChild("question");
var sum = [];
query.once("value", (snap) => {
snap.forEach( (childSnap) => {
sum.push(childSnap.val());
});
res.json(sum);
});
});
I've also tried
app.get("https://us-central1-polling-269dc.cloudfunctions.net/api/polls/get/", (req, res) => {
Which has similar results. I suspect that I'm calling the wrong URL or I need to prepare something, but I can't find information about it.
Here's my firebase.json, is something wrong here perhaps?
{
"database": {
"rules": "database.rules.json"
},
"hosting": {
"public": "client/build",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [ {
"source": "**",
"function": "app"
} ]
},
"functions": {
"predeploy": [
"npm --prefix \"$RESOURCE_DIR\" run lint"
]
}
}
Again, this works when I use a localhost and use firebase serve, but I'm trying to figure it out for Firebase Deployment online. Thanks in advance.
Okay, so I figured out the issue; you need to add the name of the exported set of functions in the call. My call should've been:
https://us-central1-polling-269dc.cloudfunctions.net/app/api/polls/get
instead of
https://us-central1-polling-269dc.cloudfunctions.net/api/polls/get
I hope this helps anyone who was having a similar issue!
Put together the below.
server.route([
{
method: "POST",
path: "/authorize",
config: {
auth: false,
cors: {
origin: ['*']
}
},
handler: (request, reply) => {
...
reply.redirect(redirectUrl)
}
}
])
I want to use with client-side JavaScript browser fetch API. The cors part is necessary to avoid using the no-cors mode for fetch and to get a non-opaque response.
If I use only 'authin the config section or onlycors` they work fine, but together hapi complaints that the configuration is wrong.
Why is that?
inside config object you cannot use key cors. for correct configuration you have to put cors key inside this like this
server.connection({
port: dbConfig.port,
routes: { cors: true } // set cross origin by hapi inbuilt property
// tls: tls
})