Angular 5 HttpClient corrupts binary downloads - angular5

When downloading a binary file from a remove server using the angular 5 http client the file is consistently corrupted. I've been unable to find resources related to this version of the client for resolving this problem. Setting the response type to either 'arraybuffer' or 'blob' does not resolve the issue.
What is the proper way to download a binary file in Angular 5 and convert it to a Uint8Array?
My current code is as follows
this.data = this.http.get(_.get(record, 'href', ''), {
observe: 'events',
reportProgress: true,
responseType: 'blob'
}))
.do(httpEvent => {
if (httpEvent.type === HttpEventType.DownloadProgress) {
this.percent.next((httpEvent.loaded / httpEvent.total) * 100);
}
})
.switchMap(httpEvent => {
if (httpEvent.type === HttpEventType.Response) {
return this.blobToArrayBuffer(httpEvent.body);
}
return Observable.of(new ArrayBuffer(0));
})
.map(buffer => {
const buff = new Uint8Array(buffer);
... // Decode buffer here
}
...
private blobToArrayBuffer(blob: Blob): Observable<ArrayBuffer> {
return Observable.create(obs => {
const fileReader = new FileReader();
fileReader.onload = () => obs.next(fileReader.result);
fileReader.onloadend = () => obs.complete();
fileReader.readAsArrayBuffer(blob);
});
}
I don't see anything obviously wrong with the response headers
HTTP/1.1 200 OK
x-amz-id-2: ...
x-amz-request-id: ...
Date: Tue, 23 Jan 2018 18:25:07 GMT
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET
Access-Control-Max-Age: 3000
Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
Last-Modified: Thu, 18 Jan 2018 22:25:33 GMT
Server: AmazonS3
ETag: ...
Accept-Ranges: bytes
Content-Type: binary/octet-stream
Content-Length: 148341
Any insight would be helpful.

Related

Donwload file with POST method in React Native and Expo

How can I download a file using the POST method along with some headers and data (of the type: "content-type: application/x-www-form-urlencoded") in React Native?
When I send a request to the URL, the following is returned in the Response Header:
content-disposition: attachment; filename="PAPR_Pginas_Web_2.pdf"
content-type: application/pdf
date: Sun, 07 Aug 2022 13:59:00 GMT
last-modified: Thu, 01 Jan 1970 00:00:00 GMT
server: Apache
strict-transport-security: max-age=86400
x-powered-by: JSF/1.2
x-xss-protection: 1; mode=block
I'm using this code:
const donwloadPDF = async (uri) => {
const downloadInstance = FileSystem.createDownloadResumable(uri, FileSystem.documentDirectory + "file.pdf");
const result = await downloadInstance.downloadAsync();
if (result.status === 200) {
Sharing.shareAsync(result.uri, { dialogTitle: "Share or Save" });
} else {
console.log("Failed to Download");
}
};
const getFile = async (payload) => {
try {
const response = await fetch(URL, {
method: "POST",
headers: headers2,
body: formBody(payload),
});
const content = await response.json();
donwloadPDF(content); // Some URI
} catch (error) {
console.error(error);
}
};
But is returned the error: JSON Parse error: Unrecognized token '%'

Accessing Set-Cookie value from response.headers in axios

I am using VueJS and Axios to send a request like this:
axiosAPI.get('/login/flows', {params: {id: 'string'}})
.then(res => {
console.log('cookie', res.headers)
}
In return server sends me this response:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: Content-Type
Cache-Control: private, no-cache, no-store, must-revalidate
Content-Length: 646
Content-Type: application/json; charset=utf-8
Date: Thu,xxxx 13:56:21 GMT
Set-Cookie: csrf_token=Lxv3zynm1Fua0hU0/W1+R2w=; Path=/.ory/kratos/public/; Domain=x.y ; Max-Age=31536000; HttpOnly; SameSite=Lax
Vary: Origin
Vary: Cookie
As you can see, server sends a csrf-token in Set-Cookies. but when I try to print out the headers I can not get and store the csrf-token. In addition, browser doesn't store the token at all in the storage section.
I need to use the csrf-token inside of this cookie but I don't know how I can do this?
Note: i don't have any access to back-end codes.
Maybe you can use the axios-cookiejar-support.
https://www.npmjs.com/package/axios-cookiejar-support
A medium article showing how to use it.
https://medium.com/#adityasrivast/handling-cookies-with-axios-872790241a9b
Sample (getting cookie from a login page):
const axios = require('axios');
const wrapper = require('axios-cookiejar-support').wrapper;
const CookieJar = require('tough-cookie').CookieJar;
const jar = new CookieJar();
const client = wrapper(axios.create({ jar }));
const url = '<your url>';
const params = new URLSearchParams();
params.append('username', '<username>');
params.append('password', '<password>');
client.post(`${url}/Login`, params, {
headers: {
'Accept': '*/*'
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Using this will get you the whole string for that header:
const cookieHeaders = res.headers['Set-Cookie'];
After that, you could split the string in an array with
cookieHeaders.split('; ');
In the array, you can then get the specific one you need.

HapiJS not accepting form-data requests

Using HapiJS 19 on Linux.
I am in the process of upgrading an older version of a back-end (hapi-16) and in the older version sending form-data would work just fine, but for some reason I get:
{
"statusCode": 415,
"error": "Unsupported Media Type",
"message": "Unsupported Media Type"
}
It seems as if I need something added to my hapi server in order to accept form-data.
Here is my server file:
const hapi = require('#hapi/hapi');
// const HapiAuthCookie = require('hapi-auth-cookie');
const CORS = { cors: true };
const SERVER_SETTINGS = { host: 'localhost', port: 8040, routes: CORS };
const server = hapi.server(SERVER_SETTINGS);
const endpoints = require('./routes.js');
// connect to database
require('../db/dbconn.js');
module.exports = {
start: async() => {
// plugin registration
await server.register([]);
server.route(endpoints,
{ prefix: '/dart-api' }
);
// start server
try {
await server.start();
console.log(`Server running on: ${server.info.uri}`);
} catch (error) {
console.log(error);
}
}
};
// Graceful server stop
process.on('SIGINT', () => {
/* eslint-disable-next-line */
console.warn('\n\n>> Stopping Hapi server ...');
server.stop({ timeout: 100 }).then((err) => {
if (err) {
console.log('Hapi server stopped');
throw err;
}
});
}); // server.stop {ends}
process.on('unhandledRejection', (err) => {
console.log(err);
throw err;
});
I'll appreciate some help.
Thanks in advance.
Update: I've done some testing with different clients with the same result. Here is the response when I use curl:
curl http://localhost:8040/users/avatars -X PUT -F 'files=#/home/ralvez/.downloads/ICONS/ricavatar.png' -vvv
* Trying 127.0.0.1:8040...
* Connected to localhost (127.0.0.1) port 8040 (#0)
> PUT /users/avatars HTTP/1.1
> Host: localhost:8040
> User-Agent: curl/7.70.0
> Accept: */*
> Content-Length: 17433
> Content-Type: multipart/form-data; boundary=------------------------0e59b1780748d1d6
>
* We are completely uploaded and fine
* Mark bundle as not supporting multiuse
< HTTP/1.1 415 Unsupported Media Type
< content-type: application/json; charset=utf-8
< vary: origin
< access-control-expose-headers: WWW-Authenticate,Server-Authorization
< cache-control: no-cache
< content-length: 86
< Date: Fri, 22 May 2020 17:27:01 GMT
< Connection: keep-alive
<
* Connection #0 to host localhost left intact
{"statusCode":415,"error":"Unsupported Media Type","message":"Unsupported Media Type"}
This make no sense to me since my handler is like this:
{
method: 'PUT',
path: '/users/avatars',
handler: users.updateAvatar,
options: {
payload: {
output: 'stream',
parse: true,
allow: 'multipart/form-data'
}
}
},
there is no doubt in my mind that this is ready to accept form-data, yet it is rejecting with "statusCode": 415, "error": "Unsupported Media Type",
what gives?!
OK. After much searching and after realizing this HAD to be related to the version of HapiJS I'm using I found someone else had the same problem.
Here is the link:
[Fix Hapi version 19.0.3 error 415 unsupported media type upload file with multipart/form-data
So I decided to change my route as follows:
{
method: 'PUT',
path: '/users/avatars',
handler: users.updateAvatar,
options: {
payload: {
output: 'stream',
parse: true,
allow: 'multipart/form-data',
multipart: true
}
}
},
and it works.
A shorter version also works:
{
method: 'PUT',
path: '/users/avatars',
handler: users.updateAvatar,
options: {
payload: {
multipart: true
}
}
},

pass sessions saved in cookies with post() automatically angular

I have seen a few bug reports on github but couldn't figure out my issue. I have cookies that the server sets. Now during POST method,I want to pass this data back to the server. It is an Observable because response from the server will determine further steps to take. Note that I have no access to the backend but CORS and credentials are set. My current code is:
public logout () : Observable<any> {
/*
Send a clear session request to cbase
*/
let vm : any = this;
const httpPostOptions =
{
headers:
new HttpHeaders (
{
"Content-Type": "application/x-www-form-urlencoded"
}),
withCredentials: true
};
return new Observable((observer) => {
vm.http.post(
Config.syncGatewayLoginStage + 'logout/', httpPostOptions
).subscribe(
data => {
observer.next(data);
},
err => { observer.error(err); console.log(err); },
() => {
observer.complete();
}
);
});
}
The server responds with error 500 that the session doesn't exist and of course, I see no session cookies passed to the server in the request header even though I see cookies set.
The server response is:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:4200
Connection: keep-alive
Content-Length: 1406
Content-Security-Policy: default-src 'self'
Content-Type: text/html; charset=utf-8
Date: Wed, 20 Feb 2019 10:09:29 GMT
Vary: Origin
X-Content-Type-Options: nosniff
X-Powered-By: Express

How to use fetch() in react native with headers json?

Postman output:
HTTP/1.0 200 OK
Cache-Control: no-cache, private
Content-Type: application/json
Date: Fri, 08 Feb 2019 12:13:36 GMT
{"status":1,"msg":"success","celeb":[{"id":1,"name":"Test Name"....
I'm getting my json in postman like this.
when I try to use fetch(), I'm getting an error json parse error, unknown identifier HTTP
fetch('https://myurl/fetch')
.then((response) => response.json())
.then((response) => {...}
let func = async () => {
const url = 'https://myurl/fetch';
const data = {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
token: await AsyncStorage.getItem(ACCESS_TOKEN), /*or whatever you have on your api*/
}),
};
const response = await fetch(url , data);
const responseData = await response.json();
console.log(responseData);
}
I believe you are missing to set to configure you API call method, headers, mode etc... Check out Fetch Examples for a better explanation.