Sending a file as binary stream with Axios POST request - http

I am trying to send a zip file to my backend which expects to get a binary stream. My code does work, but I'm afraid that I'm doing it wrong and that it might not be consistent.
function httpPostFile(inputPath: string, userName: string): Promise<AxiosResponse> {
const input = fs.createReadStream(inputPath);
const headers = {
'Content-Type': 'application/octet-stream'
};
const params = ...
const url = '/someUrl';
return axios.post(url, input, {headers: headers, params: params});
}
// then handle the promise
When I play with the numbers of the highWaterMark param of fs.createReadStream I get a 400 error more often for some values. Why? Do I have to take care of sending the data in chunks myself? Also, what happens in axios.post - how does it deal with the highWaterMark I set?

Related

Firebase function throwing timeout error when using http event

Function code below
prepay.post('/' , (req, res) => {
req.on("data", function (chunk) {
strdat += chunk;
console.log(strdat);
}).on("end", function()
{
var data = JSON.parse(strdat);
var cryp = crypto.createHash('sha512');
var text = \\ some data;
cryp.update(text);
var hash = cryp.digest('hex');
res.setHeader("Content-Type", "text/json");
res.setHeader("Access-Control-Allow-Origin", "*");
res.end(JSON.stringify(hash));
});
req.on('error', function(err){
console.log(err.message)
});
});
exports.prepay = functions.https.onRequest(prepay);
=================================
this is tried on emulator
in the logs getting ! functions: Your function timed out after ~60s. To configure this timeout, see https://firebase.google.com/docs/functions/manage-functions#set_timeout_and_memory_allocation.
\AppData\Roaming\npm\node_modules\firebase-tools\lib\emulator\functionsEmulatorRuntime.js:660 throw new Error("Function timed out.");
works fine when ran locally with nodejs using node server.js
not sure if req.on supported by firebase will be helpful if I get some reference on req.on in firebase functions
Your event-based sample of code won't work due to the preprocessing of the request that is done by the Firebase Functions SDK. Simply put, all of the 'data' and 'end' events have occurred prior to your code being executed.
Inside of functions.https.onRequest, the request is consumed and parsed according to it's content type automatically as documented here. If your request body is one of the below recognised types, it will be parsed and available as request.body. If you wish to work with the raw buffer of data, it is exposed as a Buffer as request.rawBody.
Content Type Request Body Behavior
application/json '{"name":"John"}' request.body.name equals 'John'
application/octet-stream 'my text' request.body equals '6d792074657874' (the raw bytes of the request; see the Node.js Buffer documentation)
text/plain 'my text' request.body equals 'my text'
application/x-www-form-urlencoded 'name=John' request.body.name equals 'John'
This preprocessing allows you to get to the actual function of your code faster.
prepay.post('/' , (req, res) => {
const data = req.body;
const cryp = crypto.createHash('sha512');
const text = \\ some data;
cryp.update(text);
const hash = cryp.digest('hex');
res.setHeader("Access-Control-Allow-Origin", "*");
res.json(hash);
});
exports.prepay = functions.https.onRequest(prepay);

NextJS special characters routes do not work from browser

Using NextJS, I am defining some routes in getStaticPaths by making an API call:
/**
* #dev Fetches the article route and exports the title and id to define the available routes
*/
const getAllArticles = async () => {
const result = await fetch("https://some_api_url");
const articles = await result.json();
return articles.results.map((article) => {
const articleTitle = `${article.title}`;
return {
params: {
title: articleName,
id: `${article.id}`,
},
};
});
};
/**
* #dev Defines the paths available to reach directly
*/
export async function getStaticPaths() {
const paths = await getAllArticles();
return {
paths,
fallback: false,
};
}
Everything works most of the time: I can access most of the articles, Router.push works with all URLs defined.
However, when the article name includes a special character such as &, Router.push keeps working, but copy/pasting the URL that worked from inside the app to another tab returns a page:
An unexpected error has occurred.
In the Network tab of the inspector, a 404 get request error (in Network) appears.
The component code is mostly made of API calls such as:
await API.put(`/set_article/${article.id}`, { object });
With API being defined by axios.
Any idea why it happens and how to make the getStaticPaths work with special characters?
When you transport values in URLs, they need to be URL-encoded. (When you transport values in HTML, they need to be HTML encoded. In JSON, they need to be JSON-encoded. And so on. Any text-based system that can transport structured data has an encoding scheme that you need to apply to data. URLs are not an exception.)
Turn your raw values in your client code
await API.put(`/set_article/${article.id}`)
into encoded ones
await API.put(`/set_article/${encodeURIComponent(article.id)}`)
It might be tempting, but don't pre-encode the values on the server-side. Do this on the client end, at the time you actually use them in a URL.

Deno - How to fetch data from distant API or URL?

I'm wondering how I can get data from other servers and API with deno ? Everything in the documentation teach me about making http servers and read files from local source. But I can't find anything useful about reading something on the network.
How can read JSON data from the Stripe API ? Or if I want to read a HTML file with text inside ?
Thank you for your time!
I am just giving you an example of the GET request for fetching repositories of Github.
You can change the URL and Request Configuration as per your need.
In the code given below, I am calling another API of Github. By using the fetch() method you can do that.
fetch() method first takes the URL as the first parameter and the next parameter is RequestInit which takes the request method type, headers, body, etc and at the end returning JSON response of that API call.
const githubResponse = async (): Promise<any> => {
const response = await fetch("https://api.github.com/search/repositories?q=android", {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});
return response.json(); // For JSON Response
// return response.text(); // For HTML or Text Response
}
console.log(await githubResponse());
I have written the above code in a ts file named Testing.ts . So, you can run the above code by the command given below:
deno run --allow-net Testing.ts
Next, I am giving you a sample POST request code:
const githubResponse = async (): Promise<any> => {
const body: URLSearchParams = new URLSearchParams({
q: "AvijitKarmakar",
});
const response = await fetch("https://api.github.com/search/repositories", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: body
});
return response.json();
// return response.text(); // For HTML or Text Response
}
console.log(await githubResponse());
You can see that I have created a body object and passed it in the RequestInit through the body parameter and also changed the request method type to POST.
You'll need to do a HTTP Request, for that in Deno you use fetch, the same Web API the browsers use.
To read JSON response:
const res = await fetch('https://api.stripe.com');
const data = await res.json();
If you want HTML:
const res = await fetch('https://example.com');
const html = await res.text();
// Now you can use some HTML parsing lib
fetch requires the --allow-net flag.
Deno strives to be as close to the existent browser API as possible.
That means, you can use fetch. Example:
// fetch-kitten.ts
fetch("https://placekitten.com/200/300").then(async (d) =>
Deno.writeFile("kitten.jpg", new Uint8Array(await d.arrayBuffer()))
);
CLI:
deno run --allow-net --allow-write fetch-kitten.ts
Reference

flutter: HTTP get request - disable encoding parameters

I'm trying to make a demo app with flutter and trying to fetch products from a demo magento site.
This is my code:
Future<List<Product>> fetchProducts() async {
final params = <String, String>{
'searchCriteria[filter_groups][0][filters][0][condition_type]': 'in',
'searchCriteria[filter_groups][0][filters][0][field]': 'type_id',
'searchCriteria[pageSize]': '20',
'searchCriteria[filter_groups][0][filters][0][value]': 'simple,configurable,bundle',
'searchCriteria[currentPage]': '1',
'searchCriteria[sortOrders][0][field]': 'created_at',
'searchCriteria[sortOrders][0][direction]': 'DESC'
};
var uri = Uri.parse('https://demo.com/rest/v1/default/products');
uri = uri.replace(queryParameters: params);
print(uri);
final response =
await http.get(uri, headers: {HttpHeaders.authorizationHeader: "Bearer qb7157owxy8a29ewgogroa6puwoafxxx"});
if (response.statusCode == 200) {
// If the call to the server was successful, parse the JSON.
final data = json.decode(response.body);
final products = data["items"] as List;
return products.map<Product>((json) => Product.fromJson(json)).toList();
} else {
// If that call was not successful, throw an error.
throw Exception('Failed to load post');
}
}
When I debugged, the response was 400 - Bad request. I guess that because the uri was encoded to include percentage characters as I printed as below:
So how can I disable encoding the uri?
Thank you, guys.
I believe you should replace:
var uri = Uri.parse('https://demo.com/rest/v1/default/products');
uri = uri.replace(queryParameters: params);
print(uri);
with:
var uri = Uri.https('demo.com', '/rest/v1/default/products', params);
more on this: Uri.https
more on: replace
example result:
regardless of this, if I try with your params, the library behaves normal and encodes the special characters. (see more here)
if we put the actual request in the browser to check the response:
https://demo.mage-mobile.com/rest/v1/default/products?searchCriteria[filter_groups][0][filters][0][condition_type]=in&searchCriteria[filter_groups][0][filters][0][field]=type_id&searchCriteria[pageSize]=20&searchCriteria[filter_groups][0][filters][0][value]=simple%2Cconfigurable%2Cbundle&searchCriteria[currentPage]=1&searchCriteria[sortOrders][0][field]=created_at&searchCriteria[sortOrders][0][direction]=DESC
we get the following response:
And this brings me to my initial suspicion: the API does not support this call.
Maybe you should also check this type of param from your code: 'searchCriteria[filter_groups][0][filters][0][condition_type]', it seems you are trying to acces some information from a collection but you actually writing a string...
try removing the quotes (' bla bla ') from these params id... also try to put the request direcly in the browser(or postman) to see it work.
About the encoding (changing [ to %5B) -- this is normal and it should happen.

how to make web use firebase cloud function(express) + hosting + firestore

I'm making website on firebase.
now my website is working.
but i don't know how to read firestore data and response with the data.
router.get('/', function(req, res, next) {
admin.firestore().collection('post').get()
.then(snap => {
const data = snap.size;
console.log("size: " + data);
return res.status(200).send(data);
}).catch(err => {
console.log(err);
res.status(500).send(err);
});
});
module.exports = router;
log is work but not response.
RangeError: Invalid status code: 24
at ServerResponse.writeHead (_http_server.js:192:11)
at ServerResponse.writeHead (/user_code/node_modules/express-session/node_modules/on-headers/index.js:55:19)
at ServerResponse._implicitHeader (_http_server.js:157:8)
at ServerResponse.OutgoingMessage.end (_http_outgoing.js:573:10)
at ServerResponse.end (/user_code/node_modules/express-session/index.js:354:19)
at ServerResponse.send (/user_code/node_modules/express/lib/response.js:221:10)
at admin.firestore.collection.get.then.snap (/user_code/routes/main.js:14:26)
at process._tickDomainCallback (internal/process/next_tick.js:135:7)
const data = snap.size gives you a number type variable which is the size of the collect you just queried. When you pass a number to send(), it looks like that tells Express you want to send that number as an HTTP status code to the client (and apparently it overrides what you set with status()). The API docs for send() doesn't even say that you can pass a number.
If you want to send a number as the body of the response, try converting it to a string instead:
res.status(200).send('' + data);
Or bundle it up into a JSON object for the client to parse, which is probably better.

Resources