In Node and Express, I'm trying to get all traffic sent to a URL like this.
APP.all('/testCase', function(req, res) {
console.log('Im called with the method: ' + req.method);
});
If I now do:
curl -X GET http://localhost:3000/testCase it works fine, I get the response: Im called with the method: GET
But when I do:
curl -X INSERT http://localhost:3000/testCase I'm getting: curl: (52) Empty reply from server
What Am I doing wrong? I will have many custom methods
The INSERT method is not supported by the node http parser. To see a list of the HTTP methods supported, you can run node -pe "require('http').METHODS". In order to support custom HTTP methods, one would have to patch core itself (specifically the http parser).
app.all(path, callback [, callback ...])
This method is like the standard app.METHOD() methods, except it
matches all HTTP verbs.
It’s useful for mapping “global” logic for specific path prefixes or
arbitrary matches. For example, if you put the following at the top of
all other route definitions, it requires that all routes from that
point on require authentication, and automatically load a user. Keep
in mind that these callbacks do not have to act as end-points:
loadUser can perform a task, then call next() to continue matching
subsequent routes.
The most commons HTTP methods is:
GET
HEAD
POST
PUT
DELETE
TRACE
CONNECT
Related
I am implementing a express.js project with Typescript.
I have defined a enum and a interface :
export enum ProductType {
FOOD = 'food',
CLOTH = 'cloth',
TOOL = 'tool'
}
export interface MyProduct {
type: ProductType;
info: {
price: number;
date: Date;
};
}
One of my router handler needs to return an array of MyProduct to client. I tried this :
const productArr: MyProduct[] = // call another service returns an array of MyProduct
app.get('/products', (req, res) => {
res.status(200).send({products: productArr});
});
I use Postman tested this endpoint, it responses with status 200 but with a default HTML page instead of the array of objects in JSON.
What do I miss? Is it because express.js can't automatically parse the enum and interface to json object??
P.S. I have set up json parser, so it is not about that, other endpoints work fine with json response:
const app = express();
app.use(express.json());
...
As mentioned in the comments, your code should work. I'll list some steps which can be used to try to find the problem.
Show debug info
Set DEBUG=* in your environment. DEBUG is an environment variable which controls logging for many Node modules. You'll be able to see the flow of a request through Express. If there is too much info, you can limit the output like so: DEBUG=*,-babel,-babel:*,-nodemon,-nodemon:*,-router:layer,-follow-redirects,-send (use a comma-separated list and put a - in front of any module you'd like to exclude)
This should help you trace the life of a request through the various routers and routes. You're now in a position to...
Check for another route that is short-circuiting the request
The fact that you're seeing an HTML page when the Express route is sending an object might indicate that your request is matching a different route. Look for catch-all routes such as non-middleware app.use() or wildcard routes which appear ABOVE your route.
Other suggestions
Don't explicitly set the status
Adding .status(200) is more code and unnecessary.
Use res.json()
Use .json() instead of .send(). If will always add the Content-Type: application/json header, whereas .send() will not when it cannot determine the content type (e.g. .send(null) or .send('hello') will not set the Content Type header to application/json, which may confuse clients).
As there is a lack of full response headers and server environment, assuming you are using AWS service with reverse proxy. So, there might be few possibilities listed here that need to look upon :
If router handler returns an array of object but client doesn't get them in json though response with 200 status then there might be a reverse proxy acting as a backend server, serving default content with status code 200 for unknown routes from the client. So in this scenario, you need to whitelist a new route in your reverse proxy server, assuming you are using AWS Amplify for API rewrite and redirects then you need to whitelist this route in your AWS amplify settings, or else it will serve the default content like it is happening in current scenrio.
If issue still persists then :
Make sure you have proper CORS specification on your server.
Make sure productArr is an array returned by service, because if some service returns this value - it might be an unresolved promise. So, proper test cases will help you out here or for debugging purposes set DEBUG=* in your environment and make sure it should return value as expected.
Check for another route that is short-circuiting the request: The fact that you're seeing an HTML page when the Express route is sending an object might indicate that your request is matching a different route. Look for catch-all routes such as non-middleware app.use() or wildcard routes that appear above your route.
I want to understand the internal working of Expressjs (just curious). Much of the thing are clear but I am not able to understand the chaining of routing and middleware. How expressjs add all the route and middleware to path / and how it keep the stack of route with middleware internally
So I will be very thankful to you if you provide some documentation or link from where I get the understanding how expressjs work internally
Thanks
ExpressJS is just an HTTP server allowing you to route and manipulate the received requests and returning a response.
So if you carefully look at the HTTP packet format below,
you can find the method and the path in the first line.
So, basically here express-router has a regex matcher that tries to match the HTTP request it receives to the predefined routes declared in the express application.
If you check L:43 Router, here it shows that the route you declare is just a function containing 3 constants:
path - That would be a path to match.
stack - Following a proper format, the URL is broken down using the / separator and a stack is formed in order of it's parsing, comprising another function called layer.
methods - Methods are the HTTP methods that we declare along with the path.
Parsing
So when a request is made, let's suppose: http://localhost:8000/user/1/test
We get the path: /user/1/test
The router's handle function is executed. Then this path is broken down into layers and formed a stack: ['user', '*', 'test']
This stack is then matched with that of the route objects that are pre-declared in the application and are used as Route functional objects.
As soon as it finds the match the callback is executed!
I'm trying to validate a webhook via facebook. So facebook hits my url my-url/facebook/receive within my route in nodejs i'd do res.send(req.query['hub.challenge']); to send an http response.
I'm using KoaJS. From what i understand, Koajs merges the request and response object into ctx but when reading through the docs I can't find anything along the lines of ctx.send or similar to send a http response.
Can anyone give me some direction or links.
Thanks.
To send the body of a response, you can simply do ctx.response.body = 'Hello'. There are many aliases attached to ctx, so you don't necessarily have to reference the response or request yourself. Doing ctx.body = 'Hello' would be the same as the code above.
If you wanted to set headers, you would use the ctx.set() method. For example: ctx.set('Content-Type', 'text/plain').
To access the query parameters, you would use ctx.request.query['some-key'] (or simply the alias ctx.query['some-key']).
All of the different request/response methods are documented pretty well at the Koa website along with a list of aliases attached to ctx. I highly recommend you give it a read.
I'm using Express 4.x, and I'm trying to customize the automatically generated OPTIONS response, without having to re-implement all of the functionality that express is already providing for free.
So, for example, if I have PUT and POST handlers registered on /foo, making an OPTIONS call to /foo will return an Allow header with PUT,POST, and a body with the same value. What I am trying to do is to just customize this response. So where express normally returns a body with
PUT,POST
I would like to return something like
{"methods":["PUT","POST"]}
Is there any way to do this without fully re-implementing everything express is doing behind the scenes?
The solution I found was to handle options explicitly on each route, and pull the allowed methods from req.route.methods.
app
.route('/foo')
.post(...)
.put(...)
.options(funtion(req, res, next){
var allowMethods = req.route.methods;
});
I saw an example of app.post() function. What does the '/' mean? Are we required to use post and get methods in conjunction or can we just use one method?
app.post('/', function(req, res){
return;
});
The '/' is the root directory of your website. So that function would handle post requests for foobar.com/ . You don't have to use post and get methods in conjunction. Normally I use get and only use post for routes that I want to receive post data.
The code you posted means you're setting up the server to "listen" to the root url and execute the callback when the browser hits that url.
So, assuming you're using port 80, your url would be: http://localhost:80/
Since you're using the post method, then the callback will be executed when a post request is received on that url.
If you were to instead, use the get method, then you could just navigate to that url writing it on your browser address bar.
That way you can set all the endpoints for your web app.
Edit
If you want to know when to use post, get, and the other methods, you might want to check out this answer: Understanding REST: Verbs, error codes, and authentication
when you call app.post or app.get, you are listening for post or get requests, respectively. The first argument to these calls is the route at which you are listening for the request. so in the code below:
app.post('/', function (req,res) {
res.send("hello");
}
you are telling the server to call that function when someone makes a post request to the root of your domain (mydomain.com/).
likewise, the code below would tell the server to listen for get requests at "/getroute" (mydomain.com/getroute).
app.get('/getroute', function (req, res) {
res.send('hello');
}
post requests and get requests can be used seperately and do not have to be used in conjunction on the same route.
Look, the first parameter of app.post() is the route at which post data is received, which is sent by HTML form(action = '/') mean action attribute of your form tag, it is the route at which your HTML form will send your data. So, it no connection with the app.get parameter.