In a code for a GroupMe chat bot, the variable request is defined as follows:
var request = JSON.parse(this.req.chunks[0]);
I'm trying to figure out what this means. In particlar, what is req referring to?
EDIT: Here is the function where it shows up:
function respond() {
var request = JSON.parse(this.req.chunks[0]),
botRegex = /^deadline ([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/;
botRegex2 = /^\/oranges$/;
if(request.text && botRegex.test(request.text)) {
this.res.writeHead(200);
postDeadline();
this.res.end();
} else if (request.text && botRegex2.test(request.text)) {
this.res.writeHead(200);
postOranges();
this.res.end();
} else {
console.log("don't care");
this.res.writeHead(200);
this.res.end();
}
}
req is a property on this. So that depends on what this is in this context.
Usually, req is a naming convention kept for objects representing an incoming request.
req is short for request which would be the HTTP request data from the client.
Typically, the convention is req is part of the request object on an HTTP transaction. If I had to guess form just this small snippet of code, it's a streaming request that's being parsed as JSON. The request is called by the parent object, hence this. Most likely, it's piping JSON data from an HTTP request to an API (perhaps the GroupMe API), and parsing it into an object that can be more easily used by other functions within the code.
EDIT: Unlike this, req isn't a reserved keyword. It's a convention that's commonly used when referring to HTTP transactions, but may not always hold the same context, so to say it definitively refers to a single thing would be foolish without knowing its function.
Related
I'm working with angularjs, and from my service I have to make a call to the server using a path parameter (id), query params (var1 and var2) and a body request ({"codes": ["1000"]}) - which has to be sent as an string array, within a get method (I know, sending a body request should be done within a POST).
So far, in my service I have this:
function getSub(id, var1, var2) {
var payload = {
first: var1,
second: var2
};
var url = 'sub/' + id + '/mylink'
return api.get(url, payload, {"codes": ["1000"]}).then(function (response) {
console.log("READ RESPONSE ", response);
return response;
});
};
So far, all I am getting is a bad request error linked to the response body not provided.
It may be a noob question, and not a best practice one, but I meed to find a solution for this. So far, by searching the net far and wide, I could only understand that this is an unorthodox way of using body request.
Thanks in advance!
Yes, you can send a request body with GET but it make no sense. you can parse it on the server and modify your response based on its contents, you are ignore this recommendation in the HTTP / 1.1 specification, section 4.3:
As far as I know, the standard has no statement about the body of a get type request. Thus this is a classical it depends on the implementation. Anyway, implementations tend not to support such a combination. And XMLHttpRequest is one of them:
send() accepts an optional parameter which lets you specify the request's body; this is primarily used for requests such as PUT. If the request method is GET or HEAD, the body parameter is ignored and the request body is set to null.
Specifically I am interested in changing all responses with code 403 to code 404, and changing all responses with code 301 to 302. I do not want any other part of the response to change, except the status text (which I want to be empty). Below is my own attempt at this:
addEventListener("fetch", event => {
event.respondWith(fetchAndModify(event.request));
});
async function fetchAndModify(request) {
// Send the request on to the origin server.
const response = await fetch(request);
const body = await response.body
newStatus = response.status
if (response.status == 403) {
newStatus = 404
} else if (response.status == 301) {
newStatus = 302
}
// Return modified response.
return new Response(body, {
status: newStatus,
statusText: "",
headers: response.headers
});
}
I have confirmed that this code works. I would like to know if there is any possibility at all that this overwrites part of the response other than the status code or text, and if so, how can I avoid that? If this goes against certain best practices of Cloudflare workers or javascript, please describe which ones and why.
You've stumbled on a real problem with the Fetch API spec as it is written today.
As of now, status, statusText, and headers are the only standard properties of Response's init structure. However, there's no guarantee that they will remain the only properties forever, and no guarantee that an implementation doesn't provide additional non-standard or not-yet-standard properties.
In fact, Cloudflare Workers today implements a non-standard property: webSocket, which is used to implement WebSocket proxying. This property is present if the request passed to fetch() was a WebSocket initiation request and the origin server completed a WebSocket handshake. In this case, if you drop the webSocket field from the Response, WebSocket proxying will break -- which may or may not matter to you.
Unfortunately, the standard does not specify any good way to rewrite a single property of a Response without potentially dropping unanticipated properties. This differs from Request objects, which do offer a (somewhat awkward) way to do such rewrites: Request's constructor can take another Request object as the first parameter, in which case the second parameter specifies only the properties to modify. Alternately, to modify only the URL, you can pass the URL as the first parameter and a Request object as the second parameter. This works because a Request object happens to be the same "shape" as the constructor's initializer structure (it's unclear if the spec authors intended this or if it was a happy accident). Exmaples:
// change URL
request = new Request(newUrl, request);
// change method (or any other property)
request = new Request(request, {method: "GET"});
But for Response, you cannot pass an existing Response object as the first parameter to Response's constructor. There are straightforward ways to modify the body and headers:
// change response body
response = new Response(newBody, response);
// change response headers
// Making a copy of a Response object makes headers mutable.
response = new Response(response.body, response);
response.headers.set("Foo", "bar");
But if you want to modify status... well, there's a trick you can do, but it's not pretty:
// Create an initializer by copying the Response's enumerable fields
// into a new object.
let init = {...response};
// Modify it.
init.status = 404;
init.statusText = "Not Found";
// Work around a bug where `webSocket` is `null` but needs to be `undefined`.
// (Sorry, I only just noticed this when testing this answer! We'll fix this
// in the future.)
init.webSocket = init.webSocket || undefined;
// Create a new Response.
response = new Response(response.body, init);
But, ugh, that sure was ugly.
I have proposed improvements to the Fetch API to solve this, but I haven't yet had time to follow through on them. :(
I'm creating a firebase application which uses firebase-cloud-functions.
index.js
exports.auth = functions.https.onRequest((request, response) => {
response.status(200).send({
status : "Some Status"
});
}
This is very simple functions. I want to make a POST request on the endpoint with some payload. When I tested the API using Firebase Cloud Function Emulator and POSTman with bad json
{
"phoneNumber: "9632725300"
}
The server just crashed! My question is how to handle the bad request in firebase functions like these.
with this error
The server did not crash. You have sent it a bad request (malformed JSON) and it responded perfectly with a status code 400 which is "Bad Request".
You'd rather correct your JSON...
EDIT:
If you really wanted to be able to send invalid JSON, you could do so by circumventing the JSON body parser. To do so, you could either change your request to have a content-type header set to "text/plain". This content-type will use the text body parser, which will not parse any JSON.
Note that doing so will require you to handle the JSON parsing yourself, but will permit to handle to error yourself using a try-catch.
let json;
try {
json = JSON.parse(json);
} catch (e) {
// Handle JSON error.
}
Taken from https://firebase.google.com/docs/functions/http-events
What you're experiencing is not actually a server crash. In fact, technically, by using Cloud Functions, you don't have a server to crash. (For this reason they're called "Serverless Infrastructure") Each request / operation you perform on Cloud Functions is kind of like a brand new server. Which is actually what's fantastic about Cloud Functions in general. (This is an overly simplified explanation, I'd suggest reading up a bit more about it for a better in depth explanation)
That being said, from what I understand you're trying to figure out if the JSON you got is invalid (bad) or not. Occasionally, when I have to hook up a bunch of external services, rarely, but sometimes, they return a bad JSON that my Cloud Functions can't parse, therefore throws an error.
The solution is to put your JSON.parse in to a separate function and a try / catch block like this:
function safelyParseJSON (json) {
var parsed;
try {
parsed = JSON.parse(json);
} catch (e) {
// BAD JSON, DO SOMETHING ABOUT THIS HERE.
}
return parsed; // will be undefined if it's a bad json!
}
function doSomethingAwesome () {
var parsedJSON = safelyParseJSON(data);
// Now if parsedJSON is undefined you know it was a bad one,
// And if it's defined you know it's a good one.
}
With this helper function, if you have to deal with a lot of external JSON resources, you can easily determine if the JSON you're trying to parse is good, and if not, you can at least handle the error your way.
Hope this helps :)
{\n\t"phoneNumber: "9632725300"\n}
From the screenshot, I see that the JSON is invalid or malformed. It contains newline (\n) and tab space (\t) characters. Also, the key "phoneNumber" is not wrapped in double quotes, which again invalidates the JSON.
Here's a valid format of the JSON that the server should receive
{
"phoneNumber": "9632725300"
}
I am trying to make api call to get spotify albums in native javascript without using any js frameworks. I am running into issues where I am unable to send Oauth token using native js. For spotify I have client id and client scret. I can either use that or the Oa
(function() {
var xhr = new XMLHttpRequest();
xhr.open("GET", "https://api.spotify.com/v1/albums", false);
xhr.send();
document.getElementById("results").innerHTML = xhr.responseText;
})();
function request(callback) {
var xobj = new XMLHttpRequest();
// true parameter denotes asynchronous
xobj.open('GET', YOUR_URL_HERE, true);
xobj.onreadystatechange = function () {
if (xobj.readyState == 4 && xobj.status == "200") {
// This marks that the response has been successfully retrieved from the server
// Utilize callback
callback(xobj.responseText);
}
};
xobj.send(null);
}
I would definitely recommend taking a look at the link Frobber provided. It's always better to understand why something does/doesn't work rather than just getting it to work. Here is a mock request to get you started. Hope this helps!
I think you need to read a basic tutorial on how to use XMLHttpRequest, which you can find here
One immediate problem with your code is that it's not using any callback to read the result that comes back from the server. This is all happening asynchronously, so what's occurring in your case is that you're send()ing the request, and then immediately setting innerHTML to a value that probably isn't even available from the server yet.
Check the tutorial for how to get that information back from the server when it's ready.
Note the use of the myFunction callback, and note the use of onreadystatechange. What's happening here is that send() is sending something to the server, in a separate execution thread. You need to register a callback function that will perform the data fetching and DOM update when the server reports back that the data is available, not immediately.
I've been searching on the web for some time and couldn't find an example of how to use the GitHub API from plain client-side javascript (no node-js, jquery etc). I wanted something like authenticate then push a blob, put as simply as possible so I can understand it. Shouldn't be too complicated, I bet you can do that in a dozen lines of code but I don't know a lot about ajax, json and jsonp.
Can you provide an example to get me started?
Thanks!
edit: found this: http://blog.vjeux.com/category/javascript, but I'm still confused as to what are exactly the steps of the process.
If you're looking to use with vanilla JavaScript (i.e. no framework), you need to play around with the XMLHttpRequest object. The XMLHttpRequest provides the core for AJAX implementations.
Despite the XMLHttp prefix, you're not limited to XML or HTTP. You can retrieve any data type (such as JSON) and use other protocols such as FTP.
Say we'd like to GET your user information from GitHub. From a browser, we can easily make the request by visiting https://api.github.com/users/funchal.
Sending an HTTP request in JavaScript is just as simple with XMLHttpRequest:
// Create a new request object
var request = new XMLHttpRequest();
// Initialize a request
request.open('get', 'https://api.github.com/users/funchal')
// Send it
request.send()
If you give this a go from a JavaScript console, you might feel a bit disappointed: nothing will happen immediately. You'll have to wait for the server to respond to your request. From the time you create the instantiate the request object till when the server responds, the object will undergo a series of state changes denoted by the value of the readyState property:
0 UNSENT: open() uncalled
1 OPENED: send() uncalled
2 HEADERS_RECIEVED: headers and status are available after a send()
3 LOADING: the responseText is still downloading
4 DONE: Wahoo!
Once all is finished, you can check the response attribute for the data:
request.readyState // => 4 (We've waited enough)
request.response // => "{whatever}"
When using XMLHttpRequest#open(), you have a few options to consider. Here's the method signature:
void open(
DOMString method,
DOMString url,
optional boolean async,
optional DOMString user,
optional DOMString password
);
The third parameter, which defaults to true, dictates whether the response should be made asynchronously. If you set this to false, you'll have to wait until the response is complete for #send() to return, and you'll pay the price of blocking your whole program. As such, we code in an asynchronous fashion so that our program remains responsive even while we wait. This asynchronicity is achieved by using and event listeners (a.k.a. event handlers) and callback functions.
Say we want to simply dump the response to the console once it arrives. We first need to create a callback function that we'd like to execute onload:
function dumpResponse() {
// `this` will refer to the `XMLHTTPRequest` object that executes this function
console.log(this.responseText);
}
Then we set this callback as the listener/handler for the onload event defined by the XMLHttpRequest interface:
var request = new XMLHttpRequest();
// Set the event handler
request.onload = dumpResponse;
// Initialize the request
request.open('get', 'https://api.github.com/users/funchal', true)
// Fire away!
request.send()
Now since you'll be receiving the data as a string, you'll need to parse the string with JSON.parse() to do anything meaningful. Say I want to debug the number of public repositories you have along with your name. I can use this function to parse the string into JSON, and then I can pull the attributes I want:
function printRepoCount() {
var responseObj = JSON.parse(this.responseText);
console.log(responseObj.name + " has " + responseObj.public_repos + " public repositories!");
}
var request = new XMLHttpRequest();
request.onload = printRepoCount;
request.open('get', 'https://api.github.com/users/funchal', true)
request.send()
// => Giovanni Funchal has 8 public repositories!
See the W3C spec and the Mozilla Developer Network for more info on XMLHttpRequest.