StrongLoop Loopback : How to customize HTTP response code and header - http-headers

I'm looking for a way to customize StrongLoop LoopBack HTTP response code and headers.
I would like to conform to some company business rules regarding REST API.
Typical case is, for a model described in JSON, to have HTTP to respond to POST request with a code 201 + header Content-Location (instead of loopback's default response code 200 without Content-Location header).
Is it possible to do that using LoopBack ?

Unfortunately the way to do this is a little difficult because LoopBack does not easily have hooks to modify all responses coming out of the API. Instead, you will need to add some code to each model in a boot script which hooks in using the afterRemote method:
Inside /server/boot/ add a file (the name is not important):
module.exports = function(app) {
function modifyResponse(ctx, model, next) {
var status = ctx.res.statusCode;
if (status && status === 200) {
status = 201;
}
ctx.res.set('Content-Location', 'the internet');
ctx.res.status(status).end();
}
app.models.ModelOne.afterRemote('**', modifyResponse);
app.models.ModelTwo.afterRemote('**', modifyResponse);
};

Related

Ionic 6 API REST post method headers

I'm trying to make a API REST Request but i can't connect with the api, i'd trying different options but i could do it.
This is my ts
post(emplead2){
let data = {
"LastName": this.LastName
}
this.proveedor.addStudent(data)
.subscribe(
(data)=>{this.empleados = data;},
(error)=>{console.log(error);}
)
}
this is my service
addStudent(data): Observable<any> {
const headers = new HttpHeaders().append('Content-Type','application/json');
const body = 'hola';
console.log(body)
console.log(headers)
return this.http.post('APIURL',body,{headers: headers});
}
this is the error
Access to XMLHttpRequest at 'MYAPIURL' from origin 'http://localhost:8100' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
The problem here is not from your ionic application or how you are sending the POST request. What is basically happening is that your http request is being blocked by CORS policy for security reasons. You can check here what exactly is CORS policy and why it is blocking your request.
Fixing this depends on the language/framework you built the API with, but what you need to do is allow your ionic application's base url (http://localhost:8100) to access the API and bypass the CORS policy.

Control cloudflare origin server using workers

I'm trying to use a cloudflare worker to dynamically set the origin based on the requesting IP (so we can serve a testing version of the website internally)
I have this
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
if (request.headers.get("cf-connecting-ip") == '185.X.X.X')
{
console.log('internal request change origin');
}
const response = await fetch(request)
console.log('Got response', response)
return response
}
I'm not sure what to set. The request object doesn't seem to have any suitable parameters to change.
Thanks
Normally, you should change the request's URL, like this:
// Parse the URL.
let url = new URL(request.url)
// Change the hostname.
url.hostname = "test-server.example.com"
// Construct a new request with the new URL
// and all other properties the same.
request = new Request(url, request)
Note that this will affect the Host header seen by the origin (it'll be test-server.example.com). Sometimes people want the Host header to remain the same. Cloudflare offers a non-standard extension to accomplish that:
// Tell Cloudflare to connect to `test-server.example.com`
// instead of the hostname specified in the URL.
request = new Request(request,
{cf: {resolveOverride: "test-server.example.com"}})
Note that for this to be allowed, test-server.example.com must be a hostname within your domain. However, you can of course configure that host to be a CNAME.
The resolveOverride feature is documented here: https://developers.cloudflare.com/workers/reference/apis/request/#the-cf-object
(The docs claim it is an "Enterprise only" feature, but this seems to be an error in the docs. Anyone can use this feature. I've filed a ticket to fix that...)

Aurelia Post with http-fetch-client producing an options request

I'm creating a small forum where people in our company can put up adverts for goods or services they want to sell on the fly, using aurelia. I have a list of adverts page working fine, a details page for each advert working fine both using get requests from an api. However i can't seem to get the work the Post reqeust when someone wants to add a comment on an advert.
#inject(HttpClient)
export class ApiData {
constructor(httpClient) {
httpClient.configure(config => {
config
.withBaseUrl("MyUrl");
});
this.http = httpClient;
//.configure(x => {x.withHeader('Content-Type', 'application/json');});
}
postAdvertComment(comment, id) {
return this.http.fetch(`/adverts/${id}/comments`, {
method: "post",
body: json(comment),
headers: {
'Accept': 'application/json'
}
});
}
getAdverts() {
return this.http.fetch("/adverts")
.then(response => {
return this.adverts = response.json();
});
}
getAdvert(id) {
return this.http.fetch(`/adverts/${id}`)
.then(response => {
return this.advert = response.json();
});
}
}
Doing this project we've had some issue with CORS, all solved by adding in AllowCors tags in the api, including all methods etc.
<add key="CorsAllowedOrigins" value="*" />
<add key="CorsAllowedHeaders" value="" />
<add key="CorsAllowedMethods" value="*" />
However when i try and run the post, its running an options method and returns a 400 Bad request.
Here
We also get the following CORS error:
Fetch API cannot load MyURL/api/adverts/2/comments. Response to preflight
request doesn't pass access control check: No 'Access-Control-Allow-Origin'
header is present on the requested resource. Origin 'http://localhost:49877' is
therefore not allowed access. The response had HTTP status code 400. If an
opaque response serves your needs, set the request's mode to 'no-cors' to fetch
the resource with CORS disabled.
I don't know if it's a problem with our c# api or with how I'm trying to post from aurelia, but we have tried sending requests from postman and it works fine, tried sending post request within the same app using jquery and it works fine, and all the get requests work fine, but for some reason this post is causing all sorts of problems.
It seems to be a problem in your WebAPI, but before giving you some possible solutions I'd like to show you some important things.
Postman is not affected by CORS, so all requests work.
jQuery ajax uses XHR (XmlHttpRequest object) while aurelia-fetch-client uses fetch (window.fetch. However, the fetch-polyfill uses XHR in the background). They are
different approaches to solve the same problem. Just because one of them work, doesn't actually mean that the other one should work too.
The OPTIONS request is made by fetch, that's how it works. More information here https://developers.google.com/web/updates/2015/03/introduction-to-fetch?hl=en
To solve this problem try to remove those tags from web.config, and allow CORS in your Startup.cs. Like this:
public void Configuration(IAppBuilder app)
{
app.UseCors(CorsOptions.AllowAll); //or another parameter
//rest of your code
}
You don't have to set the content-type header to application/json. It is automatically made when you use the json() function ---> body: json(comment)
If you are using OWIN you might have to send the content-type as x-www-form-urlenconded. In that case, take a look at this Post 'x-www-form-urlencoded' content with aurelia-fetch-client

Sailsjs socketio http status

I know I can call REST API of sails using socket.io. And return me the response. Following is a simple way to do that
socket.get("/", function (response) { console.log(response); })
But I also want the http status code along with response how I can get that?
If you're using the API blueprints, then the response will return the status code in the event of an error. For example, if there was a general server error, you'll get back:
{status: 500}
Otherwise, you'll get data in the response and you can assume the status was 200.
If you're using a custom controller action, then you can use any of the default responses (like res.serverError(), res.forbidden(), etc) to send back a status code, or you can set one yourself:
myAction: function (req, res) {
return res.forbidden(); // Will send {status: 403}
// OR
return res.json({status:400, error: 'Bad request!'})
}
But if you just send the status using res.json(500, {error: 'someError'}), you won't be able to retrieve it on the client.
Update
On Sails v0.10.x, using the new Sails socket client library, the request methods (io.socket.get, io.socket.post, etc) have callbacks that accept two arguments: the first being the response body (equivalent to the response in the previous client library version), and the second being an expanded response object which includes the status code, headers and more.

Using Node JS to proxy http and modify response

I'm trying to write a front end to an API service with Node JS.
I'd like to be able to have a user point their browser at my node server and make a request. The node script would modify the input to the request, call the api service, then modify the output and pass back to the user.
I like the solution here (with Express JS and node-http-proxy) as it passes the cookies and headers directly from the user through my site to the api server.
proxy request in node.js / express
I see how to modify the input to the request, but i can't figure out how to modify the response. Any suggestions?
transformer-proxy could be useful here. I'm the author of this plugin and I'm answering here because I found this page when looking for the same question and wasn't satisfied with harmon as I don't want to manipulate HTML.
Maybe someone else is looking for this and finds it useful.
Harmon is designed to plug into node-http-proxy https://github.com/No9/harmon
It uses trumpet and so is stream based to work around any buffering problems.
It uses an element and attribute selector to enable manipulation of a response.
This can be used to modify output response.
See here: https://github.com/nodejitsu/node-http-proxy/issues/382#issuecomment-14895039
http-proxy-interceptor is a middleware I wrote for this very purpose. It allows you to modify the http response using one or more transform streams. There are tons of stream-based packages available (like trumpet, which harmon uses), and by using streams you can avoid buffering the entire response.
var httpProxy = require('http-proxy');
var modifyResponse = require('http-proxy-response-rewrite');
var proxy = httpProxy.createServer({
target:'target server IP here',
});
proxy.listen(8001);
proxy.on('error', function (err, req, res) {
res.writeHead(500, {
'Content-Type': 'text/plain'
});
res.end('Something went wrong. And we are reporting a custom error message.');
});
proxy.on('proxyRes', function (proxyRes, req, res) {
modifyResponse(res, proxyRes.headers['content-encoding'], function (body) {
if (body && (body.indexOf("<process-order-response>")!= -1)) {
var beforeTag = "</receipt-text>"; //tag after which u can add data to
// response
var beforeTagBody = body.substring(0,(body.indexOf(beforeTag) + beforeTag.length));
var requiredXml = " <ga-loyalty-rewards>\n"+
"<previousBalance>0</previousBalance>\n"+
"<availableBalance>0</availableBalance>\n"+
"<accuruedAmount>0</accuruedAmount>\n"+
"<redeemedAmount>0</redeemedAmount>\n"+
"</ga-loyalty-rewards>";
var afterTagBody = body.substring(body.indexOf(beforeTag)+ beforeTag.length)+
var res = [];
res.push(beforeTagBody, requiredXml, afterTagBody);
console.log(res.join(""));
return res.join("");
}
return body;
});
});