Nuxt Proxy changes POST to GET when proxy is set to true - proxy

In my universal nuxt app, I have setted proxy at true and rewritte my url to avoid CORS issue.
But when I'm setting proxy to true, all my post requests are changed to get request. Don't understand why and how to configure it no to have this transformation.
Here is my nuxt.config.js :
/*
** Axios module configuration
*/
axios: {
proxy: true
},
proxy: {
'/apicore/': { target: 'http://blablabla.fr', pathRewrite: { '^/apicore/': '' }, changeOrigin: true }
}
My call:
async createJoueur({ state, dispatch, commit }, data) {
const URL = '/apicore/joueur'
await this.$axios
.post(
URL,
data, {
headers: {
'Content-Type': 'application/json'
}
}
)
.then((response) => {
console.log('JOUEUR LOGGED : ')
if (response.status === 200) {
} else {
console.log('Login failed / Not found')
}
}
)
.catch((error) => {
console.log('ERROR')
})
With this proxy set to true, my post-call becomes a get one.
Do I have forgotten something in my configuration?
Thanks for your help.

I was with the same problem! i solved it using changeOrigin: false.
I know that it must be the default value (Look at changeOrigin session ),
but it seems like in nuxtjs proxy implementation this value default is true (Look at Options session) .

I had the same issue and after some logging using the onProxyReq option I found out that the issue was the Cloudflare proxy, not the nuxt proxy. Cloudflare was forwarding HTTPS requests to HTTP and this forces POST requests to become GET requests as is common with 301/302 redirects.
As far as I know, it's not possible to configure Cloudflare to do 308 redirects, which would not alter the HTTP method/body.

Related

Apollo Express Server on Heroku and Refresh Token Cookie on Mobile Browser

Upon visiting/refresh, the app checks for a refresh token in the cookie. If there is a valid one, an access token will be given by the Apollo Express Server. This works fine on my desktop but when using Chrome or Safari on the iPhone, the user gets sent to the login page on every refresh.
React App with Apollo Client
useEffect(() => {
fetchUser();
}, []);
const fetchUser = async () => {
const res = await fetch('https://website.com/token', {
method: 'POST',
credentials: 'include',
});
const { accessToken } = await res.json();
if (accessToken === '') {
setIsLoggedIn(false);
}
setAccessToken(accessToken);
setLoading(false);
};
Apollo Client also checks if whether the access token is valid
const authLink = setContext((_, { headers }) => {
const token = getAccessToken();
if (token) {
const { exp } = jwtDecode(token);
if (Date.now() <= exp * 1000) {
return {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : '',
},
};
}
}
fetch('https://website.com/token', {
method: 'POST',
credentials: 'include',
}).then(async (res) => {
const { accessToken } = await res.json();
setAccessToken(accessToken);
return {
headers: {
...headers,
authorization: accessToken ? `Bearer ${accessToken}` : '',
},
};
});
});
const client = new ApolloClient({
link: from([authLink.concat(httpLink)]),
cache: new InMemoryCache(),
connectToDevTools: true,
});
This handles the token link on the Express server
app.use('/token', cookieParser());
app.post('/token', async (req, res) => {
const token = req.cookies.rt;
if (!token) {
return res.send({ ok: false, accessToken: '' });
}
const user = await getUser(token);
if (!user) {
return res.send({ ok: false, accessToken: '' });
}
sendRefreshToken(res, createRefreshToken(user));
return res.send({ ok: true, accessToken: createAccessToken(user) });
});
And setting of the cookie
export const sendRefreshToken = (res, token) => {
res.cookie('rt', token, {
httpOnly: true,
path: '/token',
sameSite: 'none',
secure: true,
});
};
Same site is 'none' as the front end is on Netlify.
After a day of fiddling and researching, I have found the issue, and one solution when using a custom domain.
The issue is that iOS treats sameSite 'none' as sameSite 'strict'. I thought iOS Chrome would be different than Safari but it appears not.
If you use your front-end, hosted on Netlify, you will naturally have a different domain than your Heroku app back-end. Since I am using a custom domain, and Netlify provides free SSL, half of the work is done.
The only way to set a httpOnly cookie is to set the cookie to secure. The next step would be to set sameSite to 'none' but as mentioned above, this does not work with iOS.
Setting the domain property of the cookie will also not work because the domain property concerns the scope of the cookie and not the cookie origin. If the cookie came from a different domain (Heroku backend), then the frontend (on Netlify) will not be able to use it.
By default, on Heroku, the free dyno will give you a domain like 'your-app.herokuapp.com', which is great because it also includes free SSL. However, for the cookie to work, I added my custom domain that I use with Netlify. To be clear, Netlify already uses my apex custom domain, so I am adding a subdomain to Heroku (api.domain.com). Cookies do work for across the same domain and subdomains with sameSite 'strict'.
The final issue with this is that the custom domain with Heroku will not get SSL automatically, which is why I think it is worth it to upgrade to a $7/month hobby dyno to avoid managing the SSL manually. This I think is the only solution when using a custom domain.
On the other hand, for those who have the same issue and would like a free solution, you can forgo using a custom domain and host your static front-end with the back-end on Heroku.
Hopefully this will save some time for anyone deploying the back-end and front-end separately.

IE 11 issue - automatically cache responses from GET requests - Reactjs

I'm making a GET request to a web service for AJAX call. Internet Explorer, is doing automatically cache responses from GET requests.
Requests work just fine for the first time i try.
As data is modified, i'm still seeing old results.
Everything appears to work correctly in other browsers.
This is the code,
export function fetchReportSet () {
return function(dispatch) {
axios.get(`${ROOT_URL}/api/reports/`, {
headers: {Pragma: 'no-cache'},
headers: {Authorization:'Token '+ localStorage.getItem('token')}
})
.then(response => {
dispatch({type: FETCH_REPORT , payload: response.data});
})
.catch(() => {
});
}
}
Any help will be appreciated.
Try to refer to this thread to add a timestamp in the url, or refer to this article to add the Cache-Control: no-cache header set.
Code like this:
import axios from 'axios';
import { cacheAdapterEnhancer } from 'axios-extensions';
const http = axios.create({
baseURL: '/',
headers: { 'Cache-Control': 'no-cache' },
// cache will be enabled by default
adapter: cacheAdapterEnhancer(axios.defaults.adapter)
});
http.get('/users'); // make real http request
this help me
axios.defaults.headers.get['Pragma'] = 'no-cache';
axios.defaults.headers.get['Cache-Control'] = 'no-cache, no-store';

API Gateway + Lambda - CORS Issue

i am experiencing continuing problems with the CORS integration for API Gateway + Lambda. i have enabled CORs for the resources associated with the API. Everything appears to work fine via Lambda testing, Postman testing etc, but calling the api from a webpage script is giving the following error "No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 415." Do I need to change the Lambda function? Thanks
Here is my simple Lambda code..
'use strict';
var AWS = require('aws-sdk');
var dclient = new AWS.DynamoDB.DocumentClient();
var getItems = (event, context, callback) => {
var params = {
TableName: "OMSCaseDataTest",
Key: {
"IncidentID": event.IncidentID
}
}
dclient.get(params, (error, data) => {
if (error) {
callback(null, "error occured")
} else {
callback(null, data);
}
});
};
exports.getItems = getItems;
If you are using proxy integration in API Gateway, then enabling CORS from API Gateway doesn't work. You have to set the Header 'Access-Control-Allow-Origin' from your Lambda code itself.
Its mentioned in the doc.
Python code sample:
response = {
'statusCode': 200,
'headers': {
'Access-Control-Allow-Origin': '*'
},
'body': json.dumps({'message': 'CORS enabled')
}
return response
Assuming you're using proxy integration, you'll need to handle the CORS yourself. Your lambda function will need to handle the HTTP methods differently. CORS problems usually occur when the pre-flight option request is not entertained. Here's a code snippet could help your cause.
function main(event, context, lambdaCallback) {
if (event.httpMethod === 'OPTIONS') {
doneOptions(200, '{"status": "OK"}', 'application/json', lambdaCallback);
} else if (event.httpMethod === 'POST') {
// do your POST here
} else {
return done(400, '{"message":"Invalid HTTP Method"}', 'application/json', lambdaCallback);
}
}
The functions that return the HTTP 200 to your frontend which decide what your frontend/API could call and what's not.
function doneOptions(statusCode, body, contentType, lambdaCallback, isBase64Encoded = false) {
lambdaCallback(null, {
statusCode: statusCode,
isBase64Encoded: isBase64Encoded,
body: body,
headers: {
'Content-Type': contentType,
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'Authorization,Content-Type',
'Access-Control-Allow-Method': 'GET,POST,OPTIONS',
}
});
}
Some times the lambda time out causes CORS error. You can increase the timeout this may fix the issue.

Vue-resource and http-proxy-middleware not routing to backend

I am new to Vue js and writing a front end for a simple task tracker app. I am trying to use vue-resource and http-proxy-middleware to have the app connect to my backend. Backend is on port 3000, and the Vue js front end is on port 8080.
I used the proxy set up described on the Vue docs.
The method:
saveTask() {
this.$http.get('/api', {title: this.taskTitle})
.then(response => {
console.log("success");
}, response => {
console.log("error");
});
}
My Proxy Table: (in config.index.js under dev)
proxyTable: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
},
When I start up the server I see:
[HPM] Proxy created: /api -> http://localhost:3000
[HPM] Proxy rewrite rule created: "^/api" ~> ""
> Starting dev server...
On the request:
GET http://localhost:8080/api 404 (Not Found)
So it looks like the proxy is not working. Any help greatly appreciated.
Your setup looks good and the requests should look like they're coming from 8080 since it is a proxy.
Are you sure something should be returning where you're looking? I have literally the same setup and it works.
My guess is since http://localhost:8080/api can't be found either can http://localhost:3000 since they're the same thing.
If that doesn't solve your problem you can dig a little deeper and debug and see if anything looks funny there.
proxyTable: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true,
logLevel: 'debug',
pathRewrite: {
'^/api': '',
},
},
},
Here goes a shot of everything working with my stuff:
what worked for me was setting up a vue.config.js file on the root dir of the vue project (that is at the same level that pacakge.json) and within that file I used this code:
module.exports = {
devServer: {
proxy: {
"^/api": {
target: "http://localhost:3000",
ws: true,
changeOrigin: true
}
}
}
}
now that the proxy was setup in the vue app the request would reach my express server :D

How do I make a CORS request with fetch on my localhost?

I'm building a React/Redux app that integrates with GitHub's API. This app will require users to sign-in using GitHub's OAuth. I'm trying to use the npm package isomorphic-fetch to do the request but cannot seem to get it to work.
Here is the Request:
require('isomorphic-fetch');
var types = require(__dirname + '/../constants/action_types');
module.exports.handleAuthClick = function() {
return function(dispatch, getState) {
var state = getState();
return fetch('http://localhost:3000/auth')
.then(function(res) {
if (res.status <= 200 && res.status > 300) {
// set cookie
// return username and token
return {
type: HANDLE_AUTH_CLICK,
data: res.json()
};
}
throw 'request failed';
})
.then(function(jsonRes) {
dispatch(receiveAssignments(jsonRes));
})
.catch(function(err) {
console.log('unable to fetch assignments');
});
};
};
Here is my Router
authRouter.get('/', function(req, res) {
res.redirect('https://github.com/login/oauth/authorize/?client_id=' + clientId);
});
And here is the Error I keep getting
Fetch API cannot load https://github.com/login/oauth/authorize/?client_id=?myclientID
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost:3000' is therefore not allowed access. If an opaque
response serves your needs, set the request's mode to 'no-cors' to fetch the
resource with CORS disabled.
Looks like this is a security option which prevents a web page from making AJAX requests to different domain. I faced the same problem, and below steps fixed it.
Firstly enable CORS in the WebService app using 'package Manager' console
PM>Install-Package Microsoft.AspNet.WebApi.Cors
Inside App_Start/WebApiConfig.cs file inside the method Register (HttpConfiguration config) add code
config.EnableCors();
Finally add the [EnableCors] attribute to the class
namespace <MyProject.Controllers>
{
[EnableCors(origins: "http://example.com", headers: "*", methods: "*")]
public class MyController : ApiController
{
//some code

Resources