Get content-type in feathers hook - feathersjs

Simple question which I havn't figured out yet.
Is there a way to get the content type of a request in a feathers hook / context?
I read about potentially using express middleware, but I want to still make use of the service, I dont want to replace it with middleware as from what I understand then I cannot make use of a feathers service afterwards.
Any hints/tips/suggestions are welcome.
Regards,
Emir

As mentioned in the FAQ it is possible to get access to the request object but it should be avoided because transport specific processing should be kept outside of services (for example, when using Feathers via websockets, there won't be a content type at all).
Service call parameters (params) for HTTP calls can be set by using a custom Express middleware so you can add a params.contentType to every service call like this (or use it as a service specific middleware):
app.use(function(req, res, next) {
req.feathers.contentType = req.headers['content-type'];
next();
});

Related

How to make RESTful routes in Cake3 without using extensions?

I want to make a RESTful API in my CakePHP application however, the only way it describes is using extensions (a.k.a file extensions) https://book.cakephp.org/3.0/en/development/routing.html#creating-restful-routes but this isn't feasible for me considering that I actually have JSON files that I do not wish to get confused with CakePHP, not only that but adding .json or whatever to the end of a path is likely to be missed and omitting it does not change that it will actually go there causing an error to show.
Is there a way to create RESTful routes without using extensions?
Extensions are optional
Extensions are by no means required for RESTful routes to work. Extensions are part of how the request handler component configures the rendering and response process, the routes themselves will work just fine without specifying extensions.
It looks like the docs are kind of outdated, the sentence describing the code example doesn't make any sense:
The first line sets up a number of default routes for easy REST access where method specifies the desired result format (e.g. xml, json, rss). These routes are HTTP Request Method sensitive.
I guess this belongs to an older code example. You may want to report this over at GitHub.
Use the Accept header
That being said, the request handler component also evaluates the Accept header, so you could make sending application/json the requirement for your API.
Also if you don't want to accept non-JSON requests at all, then you should check Request::is() and throw an exception accordingly.
if (!$this->request->is('json')) {
throw new \Cake\Network\Exception\BadRequestException():
}
Hardcode the components behavior
Furthermore it's possible to overwrite the extension that the request handler determines, and make the component think this is a JSON request:
$this->RequestHandler->ext = 'json';
It should be noted that this won't affect methods like RequestHandler::prefers()!
And finally you can also use the RequestHandler::renderAs() method to tell the request handler how to render and respond:
$this->RequestHandler->renderAs($this, 'json');
This however would need to be done in the Controller.beforeRender event in order to override the components behavior in case it identifies a request of a type that it is normally ment to handle.
See also
Cookbook > Controllers > Request & Response Objects > Checking Request Conditions
Cookbook > Controllers > Components > Request Handling > Responding To Requests
API > \Cake\Controller\Component\RequestHandlerComponent::$ext

Need to add Middleware with google assistant

I am setting up a sessionToken and for this I need to add a middleware in google assistant. Though same can be done easily using express but I am not sure how this can be achieved through google assistant web services.
Functions are, fundamentally, an Express.js server under the covers, but don't expose you to all the configuration options for Express. You have a couple of options.
The simplest is to explicitly call the middleware itself inside your function. From Google's documentation:
If you need to inject middleware dependencies for things like cookie support or CORS, call these within the function. For example, to enable CORS support, add the following block:
// Enable CORS using the `cors` express middleware.
cors(req, res, () => {
// ...
});
There are also more elaborate ways to hook into the underlying Express framework. See this stackoverflow question and answer and this followup blog post for the details.

How to serve static (or dynamic?) HTML files with RESTful API?

Hi I'm studying about RESTful API and making a website running on local to exercise.
I think RESTful is a quite good way. CRUD operations can be identified by HTTP methods and we can handle them with one url.
But most confusing things to me is that, How can we serve HTML files which are needed to request CRUD operations?
For example, If I'm implementing a forum, I need APIs to CRUD posts in forum like
[GET] /forum - see all posts in forum
[POST] /forum - create a new post
[GET] /forum/:id - see the post of id
[PUT] /forum/:id - modify the post of id
[DELETE] /forum/:id - delete the post of id
Think about how we use a forum, we need at least 3 type of HTML pages.
They are,
1. a page to see all posts in forum.
2. a page to see the specific post.
3. a page to type title and contents to create(or modify) a new post.
First and second type of HTML files can be served easily by GET requests above.
But in case of third type HTML files, I need to use extra parameters with above APIs or make a new API such like /forum/createpost to serve such HTML files.
I think, in the point of view of RESTful, I miss something and need to distinguish serving static (or dynamic) HTMLs and handling CRUD requests.
What is the bestpractices to handle this problem?
I also find some questions about this problem, but I couldn't find a clear answer.
I think you are mixing up two separate parts of the application. One is the REST API that provides the endpoints for CRUD operations. The HTML files that send the API requests are not part of the REST API. They are served by a web application that provides the front-end to the user, and makes calls to the REST API in the backend to fetch the information to display. To put it in another way, the web application making the calls is your Presentation layer. The REST API is your Business logic. Presumably, the REST API interacts with a database to write data to and read data from it. That is your Persistence or Storage layer.
You can use HTTP content type negotiation for that. POST/PUT requests (can) contain a Content-Type header declaring the type of content they're sending, and—more importantly—all requests contain an Accept header declaring the kinds of responses it accepts. If the client is accepting text/html responses, serve an HTML page; if they're accepting, say, application/json responses, serve a "RESTful" JSON response. This way your server can respond to different situations with the appropriate content and the same endpoint can serve as API and as HTML handler.
Alternatively, you can distinguish the request by using an extension: /posts.html serves a plain HTML file, while /posts gets served by a REST endpoint. That can easily be done in the web server configuration.
This might or might not be an anwser to your problem, however since you're working in Node + Express, routing might be a way to go (If I understood your question correctly). Below is an example of server implementation of accepted routes with parameters. Note, you can make parameters optional in some cases if needed.
app.get('/', function (req, res) {
res.send('Index')
})
app.get('/forum', function (req, res) {
res.send('Forum Index')
})
app.get('/forum/:id', function (req, res) {
// To access id you do 'req.params.id'
res.send('Forum Index')
})
app.put('/forum/:id', function (req, res) {
res.send('Modify Forum')
})
app.delete('/forum/:id', function (req, res) {
res.send('Delete Forum')
})
Reference : https://expressjs.com/en/guide/routing.html

MEAN.js $http.get() return index html content instead of json file

I'm doing a web app based on original MEAN.js framework. When I want to request local json test file using $http.get() method in my AngularJS file, it returned my index html content.Is it a routing problem? I didnot change the original mean.js routing code(https://github.com/meanjs/mean), just added a $http.get() method in home.client.controller.js file. Can anyone help me with this? Thanks!
That is most likely happening, because you didn't define an endpoint for that particular GET request in your app.
Everytime you make a request to your server (for example a GET request to /my-request) nodejs/express are configured in MEAN.js so that your server will try to find the endpoint for that request, if it does not find any, that request will be handled by this particular code block (specified in /modules/core/server/routes/core.server.routes.js):
// Define application route
app.route('/*').get(core.renderIndex);
Which will basically render the index view.
I'm not sure if you're using a custom module or not, eitherway, if you want that request to be handled in a different way in MEAN.js, you can specify your endpoint in your custom module routes file (or in core.server.controller.js) like so:
// Define application route
app.route('/my-request').get(core.sendMyJSON);
Be careful, because this route must be placed before the one I mentioned earlier, otherwise your request will still be handled the same way and the index view will be rendered and served again.
Then you will have to create the controller that should be called to handle that request:
exports.sendMyJSON = function (req, res) {
// logic to serve the JSON file
};
This way you should be able to get it done with a few adjustments.
Side note:
I'm not entirely sure but I think if you place your JSON file in the public directory of your app you should be able to directly access it without the need for the extra logic.

Angular.js : CORS HttpInterceptor that transforms $http.get into $http.jsonp request transparently

I've been looking into if it's possible to create a web based version of my Chrome Plugin
now that it's relying completely on Trakt.TV's JSON API.
According to angular's documentation, it's possible to intercept HTTP requests at several levels, one is the HTTP Backend itself (mainly used for testing though) and the other is HTTPInterceptor.get
The basic idea is to wrap calls to Trakt.TV's JSONP api through http://json2jsonp.com/ and have them returned transparently to get around cross site scripting restrictions. This would not only be very useful for my own project, but for a lot of other people daeling with the same issues too (therefore i'll release the module after it's done, but I want to do it properly)
The basics should be simple:
Hook the $http.get request at the right level
Overwrite the original request made
Cancel an optional other request already set up
Hook it through $http.jsonp(http://json2jsonp.com/)
Return the original promise's success/fail when done
Questions:
Has anyone built anything like this yet? (Github searches revealed nothing)
Would you suggest using the HTTPBackend or the HTTPInterceptor?
why can't you just use the jsonp helper function?
httpBakend is a mockup service to fake a backend server is not used on live code. http interceptors would do what you want you just need to attach the callback function name to your request if the url contains what ever name you want to filter and then in the response interceptor you have to pass response to the callback function so the json to be evaluated. be aware that interceptors will inspect every request makde by angular which is not very eficien, unless you are only doing calls to the tv service.
like i said before a better approach is to use $http.jsonp function
https://docs.angularjs.org/api/ng/service/$http#jsonp
a word about interceptors they need to be defined as services and then be passed to HttpProvider during your apps configuration.