NUXT Redirect issue when making a POST request to external API - api

I have a form that I built in Nuxt. I'm trying to submit it to an external API. The expected response is a JWT token.
async login() {
const res = await this.$axios.$post(`/api/token`, {
username: this.username,
password: this.password
}, this.headers )
console.log(res)
}
Trying to call the API directly gets me a CORS error, so I use proxy settings in my nuxt.confix.js.
...
modules: [
'#nuxtjs/axios',
'#nuxtjs/proxy'
],
axios: {
baseURL: '/',
proxy: true
},
proxy: {
'/api/': { target: 'https://<apiurl>.com/', changeOrigin: true }
},
...
Now when I check the network tab, it shows a 301 redirect, but the data that was sent in the post request gets thrown away, and it makes a get request to the API which returns a 405 error (because it's expecting a POST request with a data and not an empty GET request).
How can I make a POST request to an external API using NUXT? Is this an option at all?
I tried changing changeOrigin: false, and that seems to get rid of the issue, but it throws a 500 server error instead and an npm error that says
ERROR [HPM] Error occurred while proxying request localhost:3000/api/token to https://<apiurl>.com/ [ERR_TLS_CERT_ALTNAME_INVALID] (https://nodejs.org/api/errors.html#errors_common_system_errors)
Thank you

The problem is not how to send api to an external API ... the problem is in the external API it self ... make sure the external API has no credentials required to make any action ...
if you can make a request to https://jsonplaceholder.typicode.com/posts and get results that means there is no problems in your code ... cors erros in most cases are backend issue ... which means .. the backend developer who worked on it should fix it

Related

Google Strategy NestJS

I have this issue, I think I've explored all the internet for it, I'm trying to implement an authentification with passport-google-oauth20 in NestJS.
I got an event click from the front then it goes in the first part of the code
#UseGuards(GoogleAuthGuard)
public async loginGoogle(#Req() req: any) {
}
thens it goes ine the GoogleAuthGuard Part :
constructor() {
super({
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_SECRET,
callbackURL: 'http://localhost:5000/redirect',
scope: ['email', 'profile'],
});
// super({ usernameField: 'token' });
}
But in the network console part of the browser I got a CORS error 402 after a redirect 302.
Request URL: http://localhost:3000/redirect
Request Method: GET
Status Code: 302 Found
Remote Address: 127.0.0.1:3000
Referrer Policy: strict-origin-when-cross-origin
Request URL: https://accounts.google.com/o/oauth2/v2/auth?response_type=code&redirect_uri=http%3A%2F%2Flocalhost%3A5000%2Fredirect&scope=email%20profile&client_id=[MyID].apps.googleusercontent.com
Request Method: OPTIONS
Status Code: 405
Remote Address: 216.58.204.109:443
Referrer Policy: strict-origin-when-cross-origin
I already tried to enable all type of cors :
app.enableCors({
origin: ['http://localhost:5000', 'http://localhost:3000'],
allowedHeaders: ['content-type'],
credentials: true,
preflightContinue: false,
optionsSuccessStatus: 204,
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
// exposedHeaders: '*',
});
I already configured the redirection on googleapis to allow this one too. I'm out of solution if anyone could help on it, it would be really appreciated.
It feels like the Authentification is good but when it's time to redirect something goes wrong and I can't put headers in the redirect.

No Host in request URL for Grafana datasource plugin tutorial - Add authentication

I'm trying to follow the example for developing a datasource plugin from Grafana. Ultimately I want my plugin to use Oauth, but even with just the basic Grafana datasource proxy example I seem to be having issues.
I have updated my plugin.json, class and constructor.
I have setup this hard coded example.
in plugin.json
{
"path": "grafana",
"url": "https://github.com"
}
],
And a sample testDataSource()
async testDatasource() {
return getBackendSrv()
.datasourceRequest({
url: this.url + '/grafana/grafana',
method: 'GET',
})
.then(response => {
if (response.status === 200) {
return { status: 'success', message: 'Data source is working', title: 'Success' };
} else {
return { status: 'failure', message: 'Data source is not working: ' + response.status, title: 'Failure' };
}
});
}
When I try and save/test this datasource to call that method, I get in the frontend a
HTTP Error Bad Gateway
And in the logs
t=2021-09-17T14:31:22+0000 lvl=eror msg="Data proxy error" logger=data-proxy-log userId=1 orgId=1 uname=admin path=/api/datasources/proxy/9/grafana/grafana remote_addr=172.17.0.1 referer=http://localhost:3000/datasources/edit/9/ error="http: proxy error: http: no Host in request URL"
I would've expected the request to be routed to the datasource proxy and for that to make the request to github but it seems Grafana is making a request to /api/datasources/proxy/9/grafana/grafana and nothing is picking it up?
Looking up my datasource via API, there's nothing listed for URL.
You will need to render this in your ConfigEditor.tsx
<DataSourceHttpSettings
defaultUrl="http://localhost:8080"
dataSourceConfig={options}
onChange={onOptionsChange}
/>
Which will give you the basic form with URL, whitelist, auth options that you see on most plugins. The URL there I guess should match what you have in your routes.

Lyft-API - GET from Localhost

I have been trying to figure out how to get this Vue project to work with the Lyft API. I have been able to get an Auth Token successfully created from the three-legged procedure, but I am unable to get the available drive types https://api.lyft.com/v1/ridetypes endpoint from the localhost:8080. It does work on Postman.
It keeps stating:
Access to XMLHttpRequest at
'https://api.lyft.com/v1/ridetypes?lat=37.7752315&lng=-122.418075'
from origin 'http://localhost:8080' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
I had tried doing a proxy using a vue.config.js file:
module.exports = {
devServer: {
proxy: {
'/lyftapi': {
target: 'https://api.lyft.com/v1',
ws: true,
changeOrigin: true
}
}
}
}
I been around other parts of Stack Overflow, and this is the closest thing to my problem, but no answers.
CORS error in Lyft API started recently
Any suggestions?
Axios Get Call
axios.get('/ridetypes', {
baseURL: 'https://api.lyft.com/v1',
headers: {
'Authorization': this.lyftToken,
},
params: {
lat: lat.toString(),
lng: long.toString()
}
})
If it means anything, I am able to make successful GET calls to retrieve Uber products, but not so much the Auth Token (unless its from Postman).
Lyft-API has disabled CORS, this means that browsers will block calls to api.lyft.com.
Vue won't be able to do anyting about this as this is a browser security policy.
Luckily there is nothing from stoping you to make this call from your own server.
One solution is to forward the request and response using your own server. You make a call to your server, the server makes a call to lyft, waits for the response and then responds your request.
This is not a vue only solution.

webpack dev-server: Avoid proxy errors on HTTP errors returned from proxy target

I have a Vue.js project where I have configured a webpack dev-server to proxy all requests to the UI to my backend server. Here is the relevant part of vue.config.js:
devServer: {
contentBase: PATHS.build,
port: 9000,
https: false,
hot: true,
progress: true,
inline: true,
watchContentBase: true,
proxy: {
'^/': {
target: 'http://127.0.0.1:8089',
secure: false
},
}
},
I've noticed that if the HTTP response code from http://127.0.0.1:8089 is anything other than 2xx then the proxy fails with the following error:
Proxy error: Could not proxy request /api/test from localhost:9000 to http://127.0.0.1:8089.
See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (HPE_INVALID_CHUNK_SIZE).
This also causes the HTTP response code from the request to localhost:9000 to be 500 for any error and all the information about what went wrong on the server side is lost. This is problematic as I want to be able to extract information from error responses to display to the user.
I know it's possible to do because I had it working on an older Angular project which I think was using Webpack 3 (am now using Webpack 4). I tried copying all the dev-server config from this project but it just doesn't seem to work here!
EDIT: I was wrong. The Proxy error does not occur on every bad response but only for one of the requests which is a multipart file upload. Still unable to reproduce this in a smaller example to put on github though so struggling to pinpoint the cause.
This error message comes from node_modules/#vue/cli-service/lib/util/prepareProxy.js, which define a onError callback for node-http-proxy;
So I did some experiment, make back-end api generate 400 404 500 response, but I didn't got this error.
After I happen to close back-end api, error arise:
Proxy error: Could not proxy request /hello from localhost:8080 to http://localhost:8081 (ECONNREFUSED).
I search in the doc and find these:
The error event is emitted if the request to the target fail. We do not do any error handling of messages passed between client and proxy, and messages passed between proxy and target, so it is recommended that you listen on errors and handle them
So the onError do not handle error code, is called only when request fail (500 response is still treated as a complete request, connection refuse is not)
Go back to your error message, [HPE_INVALID_CHUNK_SIZE] means bad request to the back-end api. In this issue, it gives an solution: add a keep-alive header:
devServer: {
publicPath: 'http://localhost:9090/front/static-dev/build/',
port: 9090,
proxy: {
'/**': {
target: 'http://localhost:8080',
secure: false,
changeOrigin: true,
headers: {
Connection: 'keep-alive'
}
},
open: true
}
I have finally found the problem, and I apologise, it was a lot more of a specific issue than I originally thought when I wrote the question.
Issue was to do with a request which was proxied to another server using the Spring RestTemplate:
e.g.
#PostMapping("/upload")
public ResponseEntity upload(#RequestParam("file") MultipartFile file)
throws Exception {
String baseUrl = serviceProperties.getAddress();
HttpEntity<MultiValueMap<String, Object>> request = createMultipartRequest(file.getBytes());
return restTemplate.postForEntity(baseUrl + "/api/upload", filterRequest, String.class);
}
The ResponseEntity returning from the rest template proxy contained the header "Connection: close" when the response was anything other than 200 which cause the connection to close and caused this request to fail to return anything which subsequently made the dev-server proxy fail on the UI.
Fixed this by not passing the response headers from the rest template proxy to the response:
#PostMapping("/upload")
public ResponseEntity upload(#RequestParam("file") MultipartFile file)
throws Exception {
String baseUrl = serviceProperties.getAddress();
HttpEntity<MultiValueMap<String, Object>> request = createMultipartRequest(file.getBytes());
ResponseEntity response = restTemplate.postForEntity(baseUrl + "/api/upload", filterRequest, String.class);
return new ResponseEntity<>(response.getBody(), response.getStatusCode());
}

KeystoneJS Signup via Rest request

Using sydjs as book to get everything working
I'm trying to signup users via POST request via api:
/api/app/signup-email
Whenever I send data with only email&pass - everything works. If I try to add name parameter - it always fails.
Registration on front-end works as it should
Sending data as:
let parameters = [
"email": "\(email)",
"password": "\(password)",
"name": [
"first": "\(firstname)",
"last": "\(lastname)"
]
]
Maybe anyone has any idea why it doesn't work with name included? Thx.
It won't work because login request in Keystone need a _CSRF token validation, you need to provide it as parameter.
One example is first make a GET request to your login page (The CSRF Token will be in the HEADER response), save it and then make your login request passing the CSRF token obtained in the previous request.
This will be helpful KeystoneJS signin
I implemented a login against the REST-API of keystone (v4.0.0-beta.5). On the client-side I chose npm request. I enabled request's cookie-functionality (config option request.defaults({ jar: true });).
The login consisted of two separate-requests:
A simple GET-request against: https://www.yourkeystoneapp.com/keystone/session/signin
npm request will receive a cookie containing the CSRF token. There is nothing else you need to do with it. npm request will use the received cookie for all subsequent http-requests.
A POST-request containing a simple JSON body with your credentials:
{
email: 'user#yourkeystoneapp.com',
password: 'yourpassword'
}
The POST-request will be answered by Keystone with a valid user-object, if the credentials were correct.
All subsequent http-requests will be part of a valid session, as long as the CSRF-token is valid.
Code examples:
// enable cookies
request.defaults({
jar: true
});
// first request to obtain the cookie
request('https://www.yourkeystoneapp.com/signin', {/* some options */});
// second request to POST your credentials
var loginOptions = {
method: 'POST',
url: 'https://www.yourkeystoneapp.come/api/session/signin',
headers: {
'content-type': 'application/json',
'accept': 'application/json'
},
body: JSON.stringify({
email: 'user#yourkeystoneapp.com',
password: 'yourpassword
})
};
// issue POST request.
request(loginOptions);
// You are now logged in
If you are using npm request, as I did, you have to take a couple of measures to sync the requests you issue, as npm request works asynchronously. Making use of npm request's API and its callback-functions is mandatory.