we need to abort this RESTBuilder call for various reasons
RESTBuilder.PUT(url)
.file(file, CONF["fileDownloadDirectory"] + file)
.callback(
function (err, res, output) {
console.log(output.status);
}
);
Currently, RESTBuilder doesn't support aborting the request.
Related
I am new to serverless. I want to fetch data from google. I am using Google Custom Search engine. Although I got results when I run locally. But when I deploy to AWS Lambda I am getting "Internal Server Error". Can anyone help me to fix the issue?
'use strict';
var request = require('request');
module.exports.get = (event, context, callback) => {
request('https://www.googleapis.com/customsearch/v1?q=Serverless+AWS+Lambda&cx=xxxxxxxxxxx&key=API_key&num=10', function (error, response, body) {
if (!error && response.statusCode == 200) {
callback(null, response);
console.log(body);
} else {
console.warn(error);
}
});
};
I want a json output. I would like to save that result
Internal Server Error mostly points out that your lambda code could not be executed correctly. Did you pack all your dependencies (node_modules) within the ZIP file you provide to AWS lambda (e.g. request ?)
I have some web-enabled actions that are exposed through API Connect in IBM Cloud Serverless Functions.
Some of my actions use request-promises to call external REST services and I need to be able to catch an error and respond with an appropriate status-code to the caller.
Since the actions are web-enabled, the documentation indicates that I can use an annotated JSON to set the headers, status-code and body of the response. But it seems that, seems the API expects to always get a Content-Type=application/json, the response processor is failing to understand my annotations in the case of an error.
I tried the following without success:
let rp = require('request-promise');
function main(params){
//setup options
return rp(options).then(
res => {
return res;
}
).catch(
err => {
return { error: { statusCode:err.statusCode } }
}
);
}
Another variation:
let rp = require('request-promise');
function main(params){
//setup options
return rp(options).then(
res => {
return res;
}
).catch(
err => {
return { statusCode:err.statusCode }
}
);
}
The problem is that the status-code I always get is 200... I also tried to change the runtime to node8.0 without success.
Thanks!
I found the answer myself :)
In order to get the status-code and headers, one must set the field Response Content Type to `Use "Content-Type" header from action", while setting up the mapping between the API call and the action....
I have the following interceptor on my axios reponse :
window.axios.interceptors.response.use(
response => {
return response;
},
error => {
let errorResponse = error.response;
if (errorResponse.status === 401 && errorResponse.config && !errorResponse.config.__isRetryRequest) {
return this._getAuthToken()
.then(response => {
this.setToken(response.data.access_token, response.data.refresh_token);
errorResponse.config.__isRetryRequest = true;
errorResponse.config.headers['Authorization'] = 'Bearer ' + response.data.access_token;
return window.axios(errorResponse.config);
}).catch(error => {
return Promise.reject(error);
});
}
return Promise.reject(error);
}
);
The _getAuthToken method is :
_getAuthToken() {
if (!this.authTokenRequest) {
this.authTokenRequest = window.axios.post('/api/refresh_token', {
'refresh_token': localStorage.getItem('refresh_token')
});
this.authTokenRequest.then(response => {
this.authTokenRequest = null;
}).catch(error => {
this.authTokenRequest = null;
});
}
return this.authTokenRequest;
}
The code is heavily inspired by https://github.com/axios/axios/issues/266#issuecomment-335420598.
Summary : when the user makes a call to the API and if his access_token has expired (a 401 code is returned by the API) the app calls the /api/refresh_token endpoint to get a new access_token. If the refresh_token is still valid when making this call, everything works fine : I get a new access_token and a new refresh_token and the initial API call requested by the user is made again and returned correctly.
The problem occurs when the refresh_token has also expired.
In that case, the call to /api/refresh_token returns a 401 and nothing happens. I tried several things but I'm unable to detect that in order to redirect the user to the login page of the app.
I found that in that case the if (!this.authTokenRequest) statement inside the _getAuthToken method returns a pending Promise that is never resolved. I don't understand why this is a Promise. In my opinion it should be null...
I'm a newbie with Promises so I may be missing something !
Thanks for any help !
EDIT :
I may have found a way much simpler to handle this : use axios.interceptors.response.eject() to disable the interceptor when I call the /api/refresh_token endpoint, and re-enable it after.
The code :
createAxiosResponseInterceptor() {
this.axiosResponseInterceptor = window.axios.interceptors.response.use(
response => {
return response;
},
error => {
let errorResponse = error.response;
if (errorResponse.status === 401) {
window.axios.interceptors.response.eject(this.axiosResponseInterceptor);
return window.axios.post('/api/refresh_token', {
'refresh_token': this._getToken('refresh_token')
}).then(response => {
this.setToken(response.data.access_token, response.data.refresh_token);
errorResponse.config.headers['Authorization'] = 'Bearer ' + response.data.access_token;
this.createAxiosResponseInterceptor();
return window.axios(errorResponse.config);
}).catch(error => {
this.destroyToken();
this.createAxiosResponseInterceptor();
this.router.push('/login');
return Promise.reject(error);
});
}
return Promise.reject(error);
}
);
},
Does it looks good or bad ? Any advice or comment appreciated.
Your last solution looks not bad. I would come up with the similar implementation as you if I were in the same situation.
I found that in that case the if (!this.authTokenRequest) statement inside the _getAuthToken method returns a pending Promise that is never resolved. I don't understand why this is a Promise. In my opinion it should be null...
That's because this.authTokenRequest in the code was just assigned the Promise created from window.axios.post. Promise is an object handling kind of lazy evaluation, so the process you implement in then is not executed until the Promise was resolved.
JavaScript provides us with Promise object as kind of asynchronous event handlers which enables us to implement process as then chain which is going to be executed in respond with the result of asynchronous result. HTTP requests are always inpredictable, because HTTP request sometimes consumes much more time we expect, and also sometimes not. Promise is always used when we use HTTP request in order to handle the asynchronous response of it with event handlers.
In ES2015 syntax, you can implement functions with async/await syntax to hanle Promise objects as it looks synchronous.
I'm implementing a route guard (CanActivate interface) and I need to redirect to not found page under certain conditions. This can be achieved with the following sentence:
if (isNode){
let res : Response = Zone.current.get('res');
res.status(404).redirect('/not-found');
}else{
this.router.navigate(['not-found']);
}
This works, but raises an exception server side (Error: Can't set headers after they are sent), because angular2-universal still sends the rendered page, regardless of the redirection.
Is there any way to solve this properly?
Thanks in advance.
There is actually a solution for bypassing the error.
In server.ts in the res.render method add callback function and check for res.headersSent boolean.
server.get('*', (req, res) => {
res.render('../public/index.html', {req, res},
(error, html) => {
if(error)
// error handle
if (!res.headersSent) {
res.send(html);
}
});
});
Obviously, send the html only if res.headersSent is false.
I successfully implemented client editors and a server side API.
Now I'm adding more validation at the server side, and besides returning the proper HTTP code (200 for OK, 4xx for other uses, 500 for errors, etc.) I want to return a list of validations that failed after the submission generated by Model.save().
I run it this way:
myModel.save({
success: function (a, operation, c) {...},
failure: function (a, operation, c) {...}
});
But if there was a failure, the operation object only have the response status and its statusText, all through
operation.error.status // i.e. 409
operation.error.statusText // "Conflict"
But server side a detail of the failing validations (mostly domain level ones) are being added to the response.
Is there a way I can get what the server sent as the body of the HTTP response to the PUT/POST submission?
Do I have to return it using a particular JSON structure?
EDIT:
I'm now returning this as the body of the HTTP Response (with code 4xx):
{
data: {/* the record serialized */},
success: false, // or true if everything went ok
message: "This failed because X and Y."
}
Thanks in advance.
For some reason Ext is not attaching the response content to the error object, but it triggers an exception event if there is a failure.
So what we did was to handle the "exception" event of the model's proxy, and then we will have access to the XHR response, being able to do whatever we want with it.
myModel.getProxy().on('exception', this.onProxyException, this);
The handler is as follows:
onProxyException : function (proxy, response, operation) {
var errors;
errors = Ext.JSON.decode(response.responseText).message;
/* Whatever is needed with the errors */
}
In this example we asume the errors come in JSON format, they could be a simple text string, which wouldn't require the use of decode().
According to this blog:
http://code.tonytuan.org/2013/07/extjs-get-server-response-in-modelsave.html
You can write code like this:
model.save({
success: function (record, operation) {
// json response from server
console.log(operation.response);
},
failure: function (record, operation) {
// undefined
console.log(operation.response);
// json response from server
console.log(operation.request.scope.reader.jsonData);
}
});
in reader block add: messageProperty: 'message'
from server return: success:false, message: 'error test'
from failure get error:
failure: function (records, operation) {
Ext.Msg.alert('error', operation.error);
}