http post - how to send Authorization header? - rest

How do you add headers to your http request in Angular2 RC6?
I got following code:
login(login: String, password: String): Observable<boolean> {
console.log(login);
console.log(password);
this.cookieService.removeAll();
let headers = new Headers();
headers.append("Authorization","Basic YW5ndWxhci13YXJlaG91c2Utc2VydmljZXM6MTIzNDU2");
this.http.post(AUTHENTICATION_ENDPOINT + "?grant_type=password&scope=trust&username=" + login + "&password=" + password, null, {headers: headers}).subscribe(response => {
console.log(response);
});
//some return
}
The problem is, that angular doesn't add Authorization header. Instead of that, in request I can see following additional headers:
Access-Control-Request-Headers:authorization
Access-Control-Request-Method:POST
and sdch added in Accept-Encoding:
Accept-Encoding:gzip, deflate, sdch
Unfornately there is no Authorization header. How should I add it correctly?
Whole request sent by my code looks as follow:
OPTIONS /oauth/token?grant_type=password&scope=trust&username=asdf&password=asdf HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Access-Control-Request-Method: POST
Origin: http://localhost:3002
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36
Access-Control-Request-Headers: authorization
Accept: */*
Referer: http://localhost:3002/login
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,pl;q=0.6

Ok. I found problem.
It was not on the Angular side. To be honest, there were no problem at all.
Reason why I was unable to perform my request succesfuly was that my server app was not properly handling OPTIONS request.
Why OPTIONS, not POST? My server app is on different host, then frontend. Because of CORS my browser was converting POST to OPTION:
http://restlet.com/blog/2015/12/15/understanding-and-using-cors/
With help of this answer:
Standalone Spring OAuth2 JWT Authorization Server + CORS
I implemented proper filter on my server-side app.
Thanks to #Supamiu - the person which fingered me that I am not sending POST at all.

you need RequestOptions
let headers = new Headers({'Content-Type': 'application/json'});
headers.append('Authorization','Bearer ')
let options = new RequestOptions({headers: headers});
return this.http.post(APIname,body,options)
.map(this.extractData)
.catch(this.handleError);
for more check this link

I believe you need to map the result before you subscribe to it. You configure it like this:
updateProfileInformation(user: User) {
var headers = new Headers();
headers.append('Content-Type', this.constants.jsonContentType);
var t = localStorage.getItem("accessToken");
headers.append("Authorization", "Bearer " + t;
var body = JSON.stringify(user);
return this.http.post(this.constants.userUrl + "UpdateUser", body, { headers: headers })
.map((response: Response) => {
var result = response.json();
return result;
})
.catch(this.handleError)
.subscribe(
status => this.statusMessage = status,
error => this.errorMessage = error,
() => this.completeUpdateUser()
);
}

If you are like me, and starring at your angular/ionic typescript, which looks like..
getPdf(endpoint: string): Observable<Blob> {
let url = this.url + '/' + endpoint;
let token = this.msal.accessToken;
console.log(token);
return this.http.post<Blob>(url, {
headers: new HttpHeaders(
{
'Access-Control-Allow-Origin': 'https://localhost:5100',
'Access-Control-Allow-Methods': 'POST',
'Content-Type': 'application/pdf',
'Authorization': 'Bearer ' + token,
'Accept': '*/*',
}),
//responseType: ResponseContentType.Blob,
});
}
And while you are setting options but can't seem to figure why they aren't anywhere..
Well.. if you were like me and started this post from a copy/paste of a get, then...
Change to:
getPdf(endpoint: string): Observable<Blob> {
let url = this.url + '/' + endpoint;
let token = this.msal.accessToken;
console.log(token);
return this.http.post<Blob>(url, null, { // <----- notice the null *****
headers: new HttpHeaders(
{
'Authorization': 'Bearer ' + token,
'Accept': '*/*',
}),
//responseType: ResponseContentType.Blob,
});
}

I had the same issue. This is my solution using angular documentation and firebase Token:
getService() {
const accessToken=this.afAuth.auth.currentUser.getToken().then(res=>{
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': res
})
};
return this.http.get('Url',httpOptions)
.subscribe(res => console.log(res));
}); }}

Here is the detailed answer to the question:
Pass data into the HTTP header from the Angular side (Please note I am
using Angular4.0+ in the application).
There is more than one way we can pass data into the headers.
The syntax is different but all means the same.
// Option 1
const httpOptions = {
headers: new HttpHeaders({
'Authorization': 'my-auth-token',
'ID': emp.UserID,
})
};
// Option 2
let httpHeaders = new HttpHeaders();
httpHeaders = httpHeaders.append('Authorization', 'my-auth-token');
httpHeaders = httpHeaders.append('ID', '001');
httpHeaders.set('Content-Type', 'application/json');
let options = {headers:httpHeaders};
// Option 1
return this.http.post(this.url + 'testMethod', body,httpOptions)
// Option 2
return this.http.post(this.url + 'testMethod', body,options)
In the call you can find the field passed as a header as shown in the image below :
Still, if you are facing the issues like.. (You may need to change the backend/WebAPI side)
Response to preflight request doesn't pass access control check: No
''Access-Control-Allow-Origin'' header is present on the requested resource. Origin ''http://localhost:4200'' is therefore not allowed
access
Response for preflight does not have HTTP ok status.
Find my detailed answer at https://stackoverflow.com/a/52620468/3454221

if you are a ruby on rails developer and you facing a similar issue, this is because of the config of your backend: especially in api mode
so with
gem 'rack-cors' installed
goto app/config/cors.rb
Be sure to restart your server when you modify this file.
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins 'domain_name:port or just use *'
resource '*',
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head],
credentials: true
end
end
the *credentials:true line does the trick
then in your SessionController
after a user is valid for login
insert a line(this assumes you are using gem 'jwt')
token = user.generate_jwt
response.headers['Authorization'] = token
generate_jwt is a method called in model User , it is
JWT.encode(id, key, alogrithm)
If you use django, that is already taken care for you
you just have to use
installed app: restframework_simplejwt

Related

Can't override some HTTP headers with github.request() in actions/github-script workflow script

My workflow's script with action/github-script(v6) step:
const response = await github.request('POST https://example.com', {
headers: {
authorization: 'Bearer xxx',
accept: 'application/vnd.heroku+json; version=3', // I want header to be like this
'content-type': 'application/json'
},
// some other options, like request body...
});
console.log(response);
When the accept and other HTTP headers are automatically overriden with:
{
status: 400,
reponse: {}, // not important, body complains about incorrect Accept header
request: {
method: 'POST',
url: 'example.com',
headers: {
accept: 'application/vnd.github.-preview+json', // wtf?
authorization: 'token [REDACTED]', // wtf? it should start with "Bearer"
'content-type': 'application/json', // ok, as expected
'user-agent': 'actions/github-script octokit-core.js/3.5.1 Node.js/16.13.0 (linux; x64)' // ok, but I didn't set this...
},
// other stuff...
}
Now the question is what am I missing? Can I make truthly custom request using github.request() api like that?

"Content-Type" and "Content-Encoding" headers in axios

I am using axios#0.21.1 and I want to validate the response headers.
I am unable validate the headers "Content-Type" and "Content-Encoding" from a GET response.
"Content-Type": No matter what content-type i pass in request, the content-type in response is always application/JSON.
Example Code Snippet:
if (<token is present>) {
request.headers = {
authorization : 'Bearer ${token}'
}
} else {
config.auth = {}
}
config.headers = Object.assign(config.header, {
'content-type': application/<custom content>,
'accept-encoding': 'gzip, deflate, br'
}
await axios.get(endPoint, config)
.then(response => {
return response
}*
When i am checking response.header, i see that content-type is showing as "application/json" instead of the custom type. But when i hit the same url in POSTMAN i could see that content-type is as expected.
Content-Encoding: I want to validate the content-encoding in the response, but what i learnt is axios does not return content-encoding header in the response and when i check their github, they are asking to use axios.interceptors. I tried using interceptors but still i am not seeing the header in response. But this header is present in response when i try in POSTMAN. There have been some solution say CORS needs to be enabled in server side. I am strictly asking it from QA point of view because we cannot enable CORS in server side.
Any help is highly appreciable.
Try:
axios.post(your-url, {
headers: {
'Content-Encoding': 'gzip'
}
})
or
axios.post(your-url, {
headers: {
'Accept-Encoding': 'gzip',
}
})
This is by design: https://axios-http.com/docs/req_config
I also ran into this and couldn't find a solution. Ended up using node-fetch instead.

NestJS FilesInterceptor does not parse files from Axios request

I have a controller that is using FilesInterceptor to process multipart/form-data uploads.
#Post('/upload/:serial')
#UseInterceptors(FilesInterceptor('files[]'))
uploadLogFiles(
#UploadedFiles() files: UploadLog[],
#Param('serial') serial: number,
#Req() request: Request
): LogUploadResponse {
const upLoadedfiles = this.logPersistenceService.persistFiles(
files,
serial
);
return { files: upLoadedfiles };
}
}
When I submit files via a request created with Postman the files are parsed out of the request successfully.
However, when I try to create a request with Nest using the Axios based HttpService and the Form-Data library I cannot get the files from the request.
const formData = new FormData();
formData .append('files[]', 'a,b,c', fileName);
this.httpService
.post<LogUploadResponse>(
`${this.restUrl}/api/logging/upload/${serial}`,
formData,
{
headers: formData.getHeaders()
}
)
I have verified that the controller is receiving the request but files is empty. I have piped formData to a WriteStream and the contents look good and the boundary also matches what is in the header.
----------------------------347967411467094575699495
Content-Disposition: form-data; name="files[]"; filename="a.log"
Content-Type: text/plain
a,b,c
----------------------------347967411467094575699495--
REQUEST Headers { accept: 'application/json, text/plain, */*',
'content-type':
'multipart/form-data; boundary=--------------------------347967411467094575699495',
referer: 'http://localhost/',
'user-agent':
'Mozilla/5.0 (win32) AppleWebKit/537.36 (KHTML, like Gecko) jsdom/15.2.1',
'accept-language': 'en',
origin: 'http://localhost',
host: 'localhost:8081',
'accept-encoding': 'gzip, deflate',
'content-length': '17',
connection: 'keep-alive' }
Update
I am able to make it work if I use node http module directly rather than NestJS/Axios
Works
const form = new FormData();
for (const file of Object.keys(files)) {
form.append('files[]', files[file], file);
}
return new Promise<LogUploadResponse>((resolve, reject) => {
const req = request(
{
method: 'POST',
hostname: 'localhost',
port: 8081,
path: `/api/logging/upload/${serial}`,
headers: form.getHeaders()
},
res => {
res.on('error', r => {
reject(r.message);
});
res.on('data', r => {
console.log('**r', r.toString());
resolve(r.toString());
});
}
);
form.pipe(req);
Does not work
const form = new FormData();
for (const file of Object.keys(files)) {
form.append('files[]', files[file], file);
}
const req = this.httpService.request<LogUploadResponse>({
baseURL: 'http://localhost:8081',
url: `/api/logging/upload/${serial}`,
method: 'POST',
data: form,
headers: form.getHeaders()
});
return req
.pipe(
tap(resp => console.log('status', resp.status)),
map(resp => resp.data),
catchError(_err => of({ files: [] }))
)
.toPromise();
I took a look at Axios source for http.js in GitHub and it looks like it is doing a pipe on the stream data but I didn't dig too deeply.
Was never able to get the Axios version working and just implemented the node http version for this specific request in my application.

Unable to POST using Angular 7 : Header Does not work

I'm currently building out an Angular 7 App, and trying to implement the following HTTP API Call Scenario:
Request for an Application Token:
https://(URL)/token
Request Type: POST
Headers:
Accept: application/json
Request Body: empty
I have a Service class in the Angular app and the code is as follows:
import { HttpClient } from '#angular/common/http';
import { HttpHeaders } from '#angular/common/http';
The requestToken function is implemented as follows:
requestToken() {
let headers = new HttpHeaders();
headers = headers.set('Accept', 'application/json');
return this.http.post(this.configUrl + '/token', headers);
}
The Service is then called in one of the components in the App:-
getToken() {
this.service.requestToken().subscribe( res => {
console.log(res);
}, error => {
console.log(error);
});
}
When I run the App, I get a 404 Not Found error in the console. I used Postman to make an API call, setting the 'Accept' header to 'application/json' and then specifying url as https://(URL)/token and I successfully get a response. But I'm unable to make it work via Angular.
Is there something else I need to do to set the header properly in Angular? Also, I have no way to check if CORS has been enabled on the API server as this is a third-party service which I'm trying to call.
Any help would be appreciated. Thanks
Solved the problem. Changed the POST call to the following:
requestToken() {
const httpHeaders = new HttpHeaders({
'Accept': 'application/json'
});
return this.http.post(this.configUrl + '/token', { body: ''}, { headers: httpHeaders });
}
Had to add an empty 'body' parameter

Ionic 2 http post request remove default headers

I am new to Ionic 2. I make a http post request to my Spring Rest-api. As header I need to set the 'content-type': 'application/json', but the Ionic 2 sets automatically the content-type to application/json; charset=UTF-8, which is causing my REST service to respond with 415 status.
Here is my code:
register(user: User){
let headers = new Headers();
headers.append('Content-Type', 'application/json');
return this.http.post(apiUrl + 'users', user, {headers:headers})
.then((response: Response) => {
console.log(response);
console.log(JSON.stringify(user, null , 2));
console.log(JSON.stringify(headers, null, 2));
});
}
Here is the error I get when making the post request:
[00:46:35] error opening ws message: {"category":"console","type":"log","data":["error:
",{"status":415,"url":"**MY_URL**","headers":{"x-android-received-millis":"1512686795738","x-frame-options":"DENY","pragma":"no-cache","content-type":"application/json;charset=UTF-8","x-content-type-options":"nosniff","date":"Thu,
07 Dec 2017 22:46:35 GMT","strict-transport-security":"max-age=31536000 ; includeSubDomains","via":"1.1
vegur","connection":"keep-alive","x-android-sent-millis":"1512686795652","cache-control":"no-cache,
no-store, max-age=0,
must-revalidate","transfer-encoding":"chunked","server":"Cowboy","x-android-response-source":"NETWORK
415","x-android-selected-protocol":"http/1.1","expires":"0","x-xss-protection":"1;
mode=block"},"error":"{\"timestamp\":1512686795600,\"status\":415,\"error\":\"Unsupported Media
Type\",\"exception\":\"org.springframework.web.HttpMediaTypeNotSupportedException\",\"message\":\"Content
type 'application/x-www-form-urlencoded;charset=UTF-8' not supported\",\"path\":\"/api/users\"}"}]}
Check please in the error logs, the headers object. How can I leave only 'content-type': 'application/json'?
Thank you very much!