Hi I have created a azure function httptrigger to read a blob from blob storage with blob input bindings.
below is the function.json:
{
"disabled": false,
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req"
},
{
"name" : "blobContent",
"type": "blob",
"direction": "in",
"path": "containerName/{id}.{extn}",
"connection": "AzureWebJobsStorage"
},
{
"name": "$return",
"type": "http",
"direction": "out"
}
]
}
and the index.js file is :
module.exports = function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
if (req.query.id || (req.body && req.body.id)) {
context.res = {
body : {'data' : context.bindings.blobContent},
headers : {'Content-type': 'application/xml"'}
}
}
else {
context.res = {
status: 400,
body: "Please pass a object/chuck id on the query string or in the request body"
};
}
context.done(null,context.res);
};
I am using both get and post method to call the httptrigger. Since i am using blob input binding, the content is retrieved before processing index.js. With this, i couldn't validate whether the API called with id and extn. Is there a way to handle the exception and give a message back to the API caller to pass the necessary parameters. Thanks in advance.
So Functions does have some way of doing this, called Function Filters. This feature allows you to write methods that are called before or after the job function is ran (Invocation Filters), or that are invoked whenever the code encounters an exception in the functions runtime (Exception Filters). You could write an exception filter that catches an exception when the input binding fails and that would accomplish what you want.
Unfortunately, at the time of writing this answer, Function Filters are only compatible with pre-compiled C# functions. There is currently this issue tracking this feature's addition into other scenarios.
Related
I see that when we invoke a lambda, there is an x-amzn-request-id for that execution:
"resourceType": "lambda",
"resource": "invoke",
"output": {
"ExecutedVersion": "$LATEST",
"Payload": {
"recordsReady": false
},
"SdkHttpMetadata": {
"AllHttpHeaders": {
"X-Amz-Executed-Version": [
"$LATEST"
],
"x-amzn-Remapped-Content-Length": [
"0"
],
"Connection": [
"keep-alive"
],
"x-amzn-RequestId": [ <-------------------
"0b1198a6-2ed8-485b-b5f6-6c086ff192a1"
],
How would we log out that request id from the lambda using aws-sdk? Is it even possible?
context object has a couple of useful properties. One of the mis 'aws_request_id' (for python, but other sdks have it too): https://docs.aws.amazon.com/lambda/latest/dg/python-context.html
That's supposed to give you the request id for the invocation request. I would check that and log it out. E.g.:
def lambda_handler(event, context):
print(context.aws_request_id)
you could do this in JS either by
using context object, which is the most common way. context is passed as the second argument in the handler function:
exports.handler = (event, context, callback) => {
console.log(`X-Amzn-Request-Id: ${context.awsRequestId}`);
...
}
using process.env
exports.handler = (event, context, callback) => {
console.log("X-Amzn-Request-Id: " + process.env.AWS_REQUEST_ID);
// rest of your code
}
Hello I am testing out AWS Lambda and I keep getting the boilerplate output in my logs. I am new to AWS and this might be an easy fix but I have not been able to find a solution even in the docs.
Here is my index.js file
exports.handler = async (event) => {
// TODO implement
const response = {
statusCode: 200,
body: JSON.stringify('Different OutPut'),
};
return response;
};
And here is the log output in the lambda console:
Response:
{
"statusCode": 200,
"body": "\"Hello from Lambda!\""
}
Request ID:
"dc746181-ec98-4c8a-8e09-c6157da669cb"
I am expecting to have 'Different OutPut' as the body.
Also here are the role permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
Thank you for any advice.
If you keep getting Hello from Lambda! then it probably means that you haven't deployed the function before you test/execute it.
You have to explicitly deploy (orange Deploy button) function after each change in the code, so that changes take effect.
The other possibility is that you are executing wrong/old version of your function. In this case you have to explicitly select correct version if you have created any versions of your function.
Background: What I am trying to achieve is to delete multiple values from elastic using a single API call. Our app uses Node-Red to create the backend API's.
I am using below curl command to delete multiple doc id's and it is working like a charm. It deletes the docs found with id's xxxxx and yyyyy.
POST /tom-access/doc/_delete_by_query
{
"query": {
"terms": {
"_id": [
"xxxxx",
"yyyyy"
]
}
}
}
However, when I try to do the same via Node-Red (using a JavaScript function), I am getting below error.
{"error":{"root_cause":[{"type":"action_request_validation_exception","reason":"Validation
Failed: 1: query is
missing;"}],"type":"action_request_validation_exception","reason":"Validation
Failed: 1: query is missing;"},"status":400}
Here is what I have inside the Node-Red JavaScript function:
if (!msg.headers) msg.headers = {};
msg.req = {
"query": {
"terms": {
"id": [
"xxxxx",
"yyyyy"
]
}
}
};
msg.headers = {
"Content-Type": "application/json",
"Authorization" : "Basic xxxxxxxxxxxxxxxxxxxxx"
};
msg.method = "POST"
// New elastic
msg.url = "http://elastic.test.com/tom-access/doc/_delete_by_query";
return msg;
The next node makes an HTTP CALL using above msg object but results in the error mentioned above. I am new to Node-Red, JavaScript and Elastic as well. HEEELP!!!
The endpoint is probably expecting the query to be in the body of the requests.
You should be setting it under msg.payload not msg.req.
I am trying to open, read and return an HTML files using Azure functions. I am developing locally and the logs says that the function executed successfully however on the browser I am getting 500 internal server error. Am I doing something wrong in here?
const fs = require('fs');
const path = require('path');
const mime = require('../node_modules/mime-types');
module.exports = function (context, req) {
const staticFilesFolder = 'www/build/';
const defaultPage = 'index.html';
getFile(context, req.query.file);
function getFile(context, file) {
const homeLocation = process.env["HOME"];
if(!file || file == null || file === undefined){
context.done(null,{status:200,body:"<h1>Define a file</h1>",headers:{
"Content-Type":" text/html; charset=utf-8"
}});
}
fs.readFile(path.resolve(path.join(homeLocation, staticFilesFolder, file)),
(err, htmlContent) => {
if (err) {
getFile(context, "404.html");
}
else {
const res = {
status: 200,
body: htmlContent,
headers:{
"Content-Type": mime.lookup(path.join(homeLocation, staticFilesFolder, file))
}
}
context.done(null,res);
}
})
}
};
Note
I am sure that 404.html exists and index.html exists. When I log the contents of htmlContent it is giving the correct output.
functions.json
{
"disabled": false,
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"methods":["get"],
"route":"home",
"name": "req"
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
Response on Chrome
If I removed "Content-Length" header the status code changes to 406.
Update 1 The code seems to be running normally on Azure Portal but it is not working when running it locally.
It looks like you are combining two methods of returning data from an http triggered function(context.res and context.done()): https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-node#accessing-the-request-and-response
Since you are using context.res, try removing context.done();
You are making an incorrect use of context.res, you shouldn't be overwriting it but instead leveraging the methods provided by the Response class provided in the Azure NodeJS worker. If you are using using VSCode you'll get intellisense for these methods. Otherwise see: https://github.com/Azure/azure-functions-nodejs-worker/blob/dev/src/http/Response.ts
Your code should look something like this instead.
context.res.setHeader('content-type', 'text/html; charset=utf-8')
context.res.raw(htmlContent)
Using context.res.raw or context.res.send will already perform the context.done call for you.
Make sure you use content-type=text/html; charset-utf8 instead of content-type=text/html or you'll trigger an issue with the returned content-type. Instead of returning content-type=text/html you end up getting content-type=text/plain which will fail to render your html.
Addressed on: https://github.com/Azure/azure-webjobs-sdk-script/issues/2053
I have the following message, just before a failing test
Below is my piece of code
before(function(done) {
function afterListening() {
customFormats(ZSchema);
done();
}
if (app.server.listening) return afterListening();
app.on('listening', afterListening);
});
describe('/a1/{exampleID}', function() {
describe('get', function() {
it('should respond with 200 Return an array of shelter...', function(done) {
/*eslint-disable*/
var schema = {
"type": [
"object",
"null"
],
"properties": {
"meta": {
"type": [
"object",
"null"
],
"properties": {
"resource": {
"type": [
"string",
"null"
],
"description": "fully qualified URL call"
},
"version": {
"type": [
"string",
"null"
],
"description": "version of API being called"
},
"response": {
"type": [
"integer",
"null"
],
"format": "int32",
"description": "status code"
},
"required": [
"version",
"resource"
]
}
}
};
/*eslint-enable*/
api.get('/a1/example/64442')
.set('Content-Type', 'application/json')
.expect(200)
.end(function(err, res) {
if (err) return done(err);
validator.validate(res.body, schema).should.be.true;
done();
});
});
});
});
Error
1) example "before each" hook:
Error: timeout of 200ms exceeded. Ensure the done() callback is being
called in this test.
at null. (lib/runnable.js:170:19)
This error came only when I run the test case on my machine.If I run the same test case in another machine the test case is passing. why it happens.It's weird to see like this.
Any help, please!!
You generally receive timeout error, when you are not returning a promise as expected.
Done is the older implementation of the same, but no longer required. If you are using a recent version of Mocha, you should be able to just return the promise instead of calling Done().
Here are details on mocha-as-promised - which was integrated with default Mocha, since version 1.18.0.
Example of how you should return a promise:
it("should be fulfilled with 5", function () {
return promise.should.become(5);
});
In case of beforeeach - implementation should look like this:
beforeEach(() => {
const {col1, comments} = mongoose.connection.collections;
return col1.drop(() => {
// Do something after collection is dropped
});
});
Notice return for the action taken within beforeeach.
Can you please share your beforeEach with us so we can help?
Without looking, it might be because your connection to whatever thing you're connecting to isn't responding on time or isn't responding at all.
Might wanna check your connection to places where your unit tests are connecting (chances are it's the database, because it's in beforeEach() and beforeEach() doesn't require a done() to be called inside it.
Increase your timeout to something like 10 seconds or such. If you don't get database errors then, your connection is slow. If you still get timeout errors even at 10 seconds, you might have no connection at all.