Retrieving http response headers information from any website - vue.js

I'm using Vue CLI and axios.
I have a searchbar where the user can input (potentially) any website and read info about the HTTP request and response.
Some of the information I need to get are: HTTP protocol, Status code, Location (if redirected), Date and Server.
What I'm doing is a simple axios GET request taking the input from the searchbar.
I'm trying to get my head around the CORS domain issues, but even then, when I input a CORS supported site like myjson I can access only the CORS-safelisted response headers which are not what I'm looking for.
This is the axios call:
axios
.get(url)
.then((r) => {
console.log(r);
console.log(r.headers.server); //undefined
})
.catch((e) => {
console.error(e);
});
Is the brief I'm presenting even possible?
UPDATE
I've then tried removing the chrome extension I used to enable CORS requests and installed Moesif Origin & CORS Changer extension. After restarting my PC I have now access to the remaining response headers.
I don't really know exactly what went wrong with the previous extension, but hopefully this helps somebody.
It's also worth pointing out that at the current date I'm writing this edit, myjson site has been flagged by chrome as non-safe for privacy issues. I've simply made HTTP requests to other sites and got the response headers as described.

The response to a cross-origin request for https://myjson.dit.upm.es/about contains the CORS-related headers
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, PATCH, PUT, DELETE, POST, OPTIONS
but no Access-Control-Expose-Headers. Without that, a cross-origin client cannot access the Server header, because it is not CORS-safelisted.
It would work if you had your server make the request and evaluate the headers, not the axios client.

Related

CORS header Allow-Origin missing in POST requests

I know there are tons of CORS related questions but I can't seem to find the answer to this one.
This is my server side golang code (We are using github.com/rs/cors go module):
We basically have set of apis that require an authorization header and some apis that don't (think checkout vs checkout as guest functionality)
allowedOrigins := []string{"http://localhost:3000", "http://localhost:3001"}
//allowedHeaders := []string{"Authorization"}
c := cors.New(cors.Options{AllowedOrigins: allowedOrigins, AllowCredentials: true})
handler := c.Handler(r)
What i found is the following:
// if allowcredentials is set to true, then all non auth requests go through but all auth requests return cors error
// if allowedHeaders: authorization is set then all **authenticated and NON authenticated** POST requests fail. GET works fine for both cases.
More specifically: The error I get is that AllowedOrigins is not set (??.. I get this in the PRE-FLIGHT OPTIONS response headers) when I try to execute a POST request and I set the AllowedHeaders:authorization option above.
If I comment that line (As you see above) then the non auth requests go through perfectly and the AllowedOrigins hader is sent back in the OPTIONS request..
Fixed it....
https://github.com/rs/cors
Has a nice CorsOptions Debug:true. I used that to inspect what was going on and the moment i hardcoded that I allowed Authorization to come into my server then the POST request was complaining afterwards because I was also sending content-type (automatically sent by client (axios), I didn't specify it).. and Server was saying pretty much "I only recognize authorization header"... I added Content-Type and it now works!
allowedHeaders := []string{"Authorization", "Content-Type"}

Navigator.sendBeacon not working with Authorization Headers

Recently chrome stop support for synchronos xmlhttprequest on page unload or beforeunload event https://www.chromestatus.com/feature/4664843055398912
i try this solution Perform an asynchronous service get when closing browser window / tab with Angular but not seems to be working in latest chrome versions
Now i am using navigator.sendbeacon api like this
let headers = {
type: 'application/json; charset=utf-8',
'authorization': `bearer ${token}`
}
let blob = new blob([json.stringify({a:"9"})], headers);
navigator.sendbeacon(uri, blob);
Api is throwing 401 so seems like authorization is not working,
Is there any other alternative to navigator.sendBeacon
At time of this writing, no. Chrome (and probably other browsers too more sooner than later) will disallow XHR-sync because of bad UX to the user (the browser hangs if user is closing the tab and an XHR-sync request is made).
There are a few workarounds though, but each have their drawbacks as well
Use the new (and experimental) sendBeacon API - sendBeacon simply "queues" the request and this guarantees that the request will be fired even on page unload. That too without blocking the UX. Some limitations with this are that you cannot change request headers by default. If you DO need to add custom headers, you will have to use a blob, and that too the headers should be CORS-friendly. And will not work on older browsers (looking at you, IE)
Use fetch() API + keepalive flag - but this again works if you request headers are on the CORS-safelist. Basically if your fetch() request has certain request headers, then a preflight request can be made for security reasons. If such a preflight request is made, then the fetch() + keepalive is disallowed by some browsers. Basically you need to keep your request simple for this to work. For example, Such as you cannot use a content-type=application/json here. One workaround for this is to send data as text/plain and get your server to handle it accordingly.
Some more info on CORS simple vs preflight requests can be found here.
Chrome does allow a temporary workaround but this will work only till Oct 2020. More info on that here.

Cross-Origin Request Blocked error in HTTPS request

I have a standard HTTPS Axios request from my Frontend (which is based on Vue), to the our company's API which is on another server(server use SSL sertificate).
testApi() {
axios.get('https://rng-hub2.staging.rng:8001/rng/3/')
.then(function (response) {
// handle success
console.log(response);
})
.catch(function (error) {
// handle error
console.log(error);
})
.finally(function () {
// always executed
});
},
Which cause an error like this:
In Firefox:
In Chrome the error looks like this:
As I was thinking, in browsed developing tools under tab of Netwerk -> Response, I should also see an error, which is true for Chrome, but eventyally is not true for Firefox.
So Chrome shows me:
But in the Firefox I receive my data in exactly right format:
Have any idea how I can retrieve this data correctly and assign it to the response variable in .then section?
About Cross-Origin Request Blocked error: API's server administrator told me, that he have added my IP to the CORS "trusted list". However I'm not sure, because according to this post: https://jonhilton.net/cross-origin-request-blocked/
in my Response Header I should receive an additional header with my local IP like:
Access-Control-Allow-Origin: http://192.168.32.44
But I'm not.
This proxy staff also didn't work:
How to deal with CORS error on Vue CLI 3?
Please give me hint what am I doing wrong
Found the solution. The problem was deeper then I thought. So short answer is: If you are working in local network, with different API servers, they might be certified with inner corporate CA (Certificate authority) to be able to communicate via HTTPS protocol. So what you need is, to ask from your server administrator to give you private_key with which you gonna sign all the request to a specific API. In guzzle its looks like this:
new GuzzleClient(['verify' => '/path/to/self-signed/cert.pem']);

Why can't add headers to axios.get?

I'm using axios and vue.js to play with the Fortnite Tracker API.
In their documentation it's clearly said that we need to include the "TRN-Api-Key" in header.
I tested with Postman and It works.
And this is my axios function to make the request:
let url = `https://api.fortnitetracker.com/v1/profile/${this.platform}/${this.username}`;
// username and platform are from my Vue Component.
axios.get(url, {
headers: {
"TRN-Api-Key": "xxxxxxxx-xxxx-xxxx-xxxx-xxxx" // of course from my account on their website.
}
})
.then(response => console.log(response.data))
I expect the output in json like in Postman but I had a 404 Error: "Network Error".
And in the Browser Network Debug I can't see the request header 'TRN-Api-Key'.
[EDIT]
If your app is running on a server you can write a short PHP-Script and use curl in it to access the API (I think it's even possible to generate PHPcode from Postman).
Just address this script with axios and submit your platform and usernameproperties to build the right url.
Or have a look at this post alternatively. Maybe the use of an other API like #kecinotrab provided in the acceptet answer will help you too.

how to skip Preflight Requset in vue with content-type:application/json

error :"405 not allowed Method" in post method type call in request command vue
i need call api function with content-type:application/json and post Method type with request command in vue ,but browser add preflight request with options method type and it causes this error :"405 not allowed Method"
var options = {
method: "POST",
url: "http://api.sample.com/login",
headers: {
"Access-Control-Request-Method":"POST",
"cache-control": "no-cache",
"content-type": "application/json",
},
body: '{ Username: "demo", Password: "demo", Domain: "test" }'
};
request(options, function(error, response, body) {
if (error) throw new Error(error);
body.data;
alert("ok");
});
The OPTIONS call is done whenever you do a cross-origin request. This means the domain your application is running on is different from the domain where the api is. A pre-flight request is mandatory for these requests, because the browser needs to figure out if you are allowed to do these requests. A 405 error means that the server thinks you are not allowed to make that request.
To solve this problem you can move your api to the same domain as your frontend. Please note that it cannot be on a subdomain.
A different way of solving this, is by sending back the correct headers. In your case you seem to at least miss the Access-Control-Allow-Methods response header. Make sure to send this header and either dynamically figure out which methods are allowed, or do something like the following. That would allow the most common methods to work.
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
In the comments you said that you do not have control over the api, and as such cannot change the response header. In that case your best bet is to contact whoever maintains the api and ask how to best use their api.
In the comments you said that this worked fine when you did the same thing in ASP.NET. ASP.NET is a server-side language, which means that requests in that context do not have a concept of "cross-origin". Cross-origin only comes into play in the browser, where the application runs on an actual domain.
Assuming you can set up a proxy on your application domain, you can also create a proxy that proxies all requests to the api you actually want to communicate with. You would deploy your domain on https://example.com and do your requests to https://example.com/api/endpoint. Your proxy will listen for requests that begin with https://example.com/api and proxy it to https://whatever.the.api.is/ with the appropriate endpoint and data.
Please keep in mind that while some api's might just be configured incorrectly, a lack of cross-origin response headers might just mean that the api is nog meant to be consumed through the browser. Part of this could be that the request contains a secret that should not be exposed to users that use your application, but should instead only be on the server. Using a proxy in that case would set you up for impersonation attacks, because you would expose the secret to your application, but defeat the cross-origin headers by making it appear to the application that the api is on the same domain.