TypeError: req.set is not a function
santhoshdc1590 opened this issue · 6 comments
I used the function.py
's handle_http
as my cloud function to be built
def handle_http(req):
biquery_client = bigquery.Client(credentials=get_credentials())
if req.method == 'OPTIONS':
return JsonResponse({"status":"success"},status=200,safe=False)
if req.method == 'GET':
print("Body: ",type(req.GET.getlist('image')))
print(type(req.GET.getlist('image')),req.GET.getlist('image'))
i=req.GET.getlist('image')
i=''.join(str(e) for e in i)
print(i)
rID = req.GET.getlist('refID')
rTable = req.GET.getlist('refTable')
print(rID," ",rTable)
########### main custom function. which I am calling ##################
mainP(i,rID,rTable)
return Response(
status_code=200,
body={'key': 2},
headers={'content-type': 'application/json'},
)
handle_http_event(handle_http)
This was the index.js
generated after the build below
var googleAuth = require('google-auto-auth')();
//Handle Background events according to spec
function shimHandler(data) {
return new Promise((resolve, reject) => {
googleAuth.getToken(function (err, oauthToken) {
if (err) {
reject()
} else {
const p = require('child_process').execFile('./dist/func/func', {
env: Object.assign(process.env, {
'GOOGLE_OAUTH_TOKEN': oauthToken,
})
});
var lastMessage;
p.stdin.setEncoding('utf-8');
//Log standard err messages to standard err
p.stderr.on('data', (err) => {
console.error(err.toString());
})
p.stdout.on('data', (out) => {
console.log(out.toString());
lastMessage = out;
})
p.on('close', (code) => {
if (code !== 0) {
//This means the shim failed / panicked. So we reject hard.
reject();
} else {
// Resolve the promise with the latest output from stdout
// In case of shimming http, this is the response object.
resolve(lastMessage);
}
});
//Write the object/message/request to the shim's stdin and signal
//End of input.
p.stdin.write(JSON.stringify(data));
p.stdin.end();
}
});
});
}
//Handle http request
function handleHttp(req, res) {
var requestBody;
switch (req.get('content-type')) {
case 'application/json':
requestBody = JSON.stringify(req.body);
break;
case 'application/x-www-form-urlencoded':
//The body parser for cloud functions does this, so just play along
//with it, sorry man! Maybe we should construct some kind of proper
//form request body? or not. let's keep it this way for now, as
//This is how cloud functions behaves.
req.set('content-type', 'application/json')
requestBody = JSON.stringify(req.body);
break;
case 'application/octet-stream':
requestBody = req.body;
break;
case 'text/plain':
requestBody = req.body;
break;
}
var fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
var httpRequest = {
'body': requestBody,
'headers': req.headers,
'method': req.method,
'remote_addr': req.ip,
'url': fullUrl
};
shimHandler(httpRequest)
.then((result) => {
data = JSON.parse(result);
res.status(data.status_code);
res.set(data.headers)
res.send(data.body);
})
.catch(() => {
res.status(500).end();
})
}
//
exports['handle_http'] = function(req, res) {
return handleHttp(req, res);
}//
When testing the url generated locally using POSTMAN
I'm getting this error
{"stack":"TypeError: req.set is not a function\n at handleHttp (/Users/santhoshdc/Documents/LaunchTestOne/cloudfn/target/index.js:55:11)\n at exports.handle_http (/Users/santhoshdc/Documents/LaunchTestOne/cloudfn/target/index.js:90:10)\n at app.use (/Users/santhoshdc/.nvm/versions/node/v9.8.0/lib/node_modules/@google-cloud/functions-emulator/src/supervisor/worker.js:142:11)\n at Layer.handle [as handle_request] (/Users/santhoshdc/.nvm/versions/node/v9.8.0/lib/node_modules/@google-cloud/functions-emulator/node_modules/express/lib/router/layer.js:95:5)\n at trim_prefix (/Users/santhoshdc/.nvm/versions/node/v9.8.0/lib/node_modules/@google-cloud/functions-emulator/node_modules/express/lib/router/index.js:317:13)\n at /Users/santhoshdc/.nvm/versions/node/v9.8.0/lib/node_modules/@google-cloud/functions-emulator/node_modules/express/lib/router/index.js:284:7\n at Function.process_params (/Users/santhoshdc/.nvm/versions/node/v9.8.0/lib/node_modules/@google-cloud/functions-emulator/node_modules/express/lib/router/index.js:335:12)\n at next (/Users/santhoshdc/.nvm/versions/node/v9.8.0/lib/node_modules/@google-cloud/functions-emulator/node_modules/express/lib/router/index.js:275:10)\n at app.use (/Users/santhoshdc/.nvm/versions/node/v9.8.0/lib/node_modules/@google-cloud/functions-emulator/src/supervisor/worker.js:114:7)\n at Layer.handle [as handle_request] (/Users/santhoshdc/.nvm/versions/node/v9.8.0/lib/node_modules/@google-cloud/functions-emulator/node_modules/express/lib/router/layer.js:95:5)","message":"req.set is not a function","name":"TypeError"}
@MartinSahlen or anyone else who knows what's going on here, help please?
What is going on is that this line: https://github.com/MartinSahlen/cloud-functions-python/blob/master/cloudfn/template/index.js#L55 tries to call the function set
which does not seem exist on the request object and thereby fails. Likely because noone so far has tried using a cloud function for posting form data - or it existed in a previous version of express and you seem to be using the emulator. It should be an easy fix to go around this bug - feel free to submit a pull request to fix this @santhoshdc1590 👍
I'm new to this web
thing. I do understand that the req.set
doesn't exist for the program to call it. I'm unable to find an alternative for req.set
. Yes I'm using emulator. express
is new to me again. Would really appreciate if you could guide me through this 😅
Unfortunately I do not have a lot of time to provide guidance but I can try to fix the bug when I can carve out some time.
@MartinSahlen I couldn't find any function called req.set
in express2.x or express3.x can I use req.accepts('application/json')
instead to req.set('content-type', 'application/json')
from express4.x?
I think it can be just removed, is it is an error on my end as I said. Since JavaScript is not statically typed this error is not caught and occurs at runtime when posting data using forms.
I commented the req.set
, built and installed cloud function python again.
Built and deployed the function similarly locally.
Now I am not getting 500 internal server error
on POSTMAN
and black screen
in browser
I tried changing https://github.com/MartinSahlen/cloud-functions-python/blob/master/cloudfn/template/index.js#L55 and checked what's happening
This is the changed program
var googleAuth = require('google-auto-auth')();
//Handle Background events according to spec
function shimHandler(data) {
return new Promise((resolve, reject) => {
googleAuth.getToken(function (err, oauthToken) {
if (err) {
reject()
} else {
const p = require('child_process').execFile('./dist/{{config["output_name"]}}/{{config["output_name"]}}', {
env: Object.assign(process.env, {
'GOOGLE_OAUTH_TOKEN': oauthToken,
})
});
var lastMessage;
p.stdin.setEncoding('utf-8');
//Log standard err messages to standard err
p.stderr.on('data', (err) => {
console.error(err.toString());
})
p.stdout.on('data', (out) => {
console.log(out.toString());
lastMessage = out;
})
p.on('close', (code) => {
if (code !== 0) {
//This means the shim failed / panicked. So we reject hard.
reject();
} else {
// Resolve the promise with the latest output from stdout
// In case of shimming http, this is the response object.
resolve(lastMessage);
}
});
//Write the object/message/request to the shim's stdin and signal
//End of input.
p.stdin.write(JSON.stringify(data));
p.stdin.end();
}
});
});
}
//Handle http request
function handleHttp(req, res) {
var requestBody;
console.log('hello')
console.log(req.get('content-type'))
switch (req.get('content-type')) {
case 'application/json':
requestBody = JSON.stringify(req.body);
break;
case 'application/x-www-form-urlencoded': //application/x-www-form-urlencoded
//The body parser for cloud functions does this, so just play along
//with it, sorry man! Maybe we should construct some kind of proper
//form request body? or not. let's keep it this way for now, as
//This is how cloud functions behaves.
//req.setHeader('content-type', 'application/json')
requestBody = JSON.stringify(req.body);
console.log('this should be the case, the result of switch statement');
requestBody = JSON.stringify(req.body);
console.log('Request body is: ');
console.log(requestBody);
break;
case 'application/octet-stream':
requestBody = req.body;
break;
case 'text/plain':
requestBody = req.body;
break;
}
var fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;
var httpRequest = {
'body': requestBody,
'headers': req.headers,
'method': req.method,
'remote_addr': req.ip,
'url': fullUrl
};
shimHandler(httpRequest)
.then((result) => {
console.log('should come here')
data = JSON.parse(result);
res.status(data.status_code);
res.set(data.headers)
res.send(data.body);
})
.catch((e) => {
console.log(e);
console.log('some error has occurred');
res.status(500).end();
})
}
//{% if config["trigger_http"] %}
exports['{{config["function_name"]}}'] = function(req, res) {
return handleHttp(req, res);
}//{% else %}
exports['{{config["function_name"]}}'] = function(event, callback) {
return shimHandler(event.data).then(function() {
callback();
}).catch(function() {
callback(new Error("Function failed"));
});
}//{% endif %}
This is what I get on running logs using functions logs read
2018-03-23T13:37:16.389Z - info: User function triggered, starting execution
2018-03-23T13:37:16.389Z - info: hello
application/x-www-form-urlencoded
this should be the case, the result of switch statement
Request body is:
{}
2018-03-23T13:37:16.410Z - info: undefined
2018-03-23T13:37:16.411Z - info: some error has occurred
2018-03-23T13:37:16.415Z - info: Execution took 29 ms, user function completed successfully