I'm using Nock to intercept a http request.
test.js:
const nock = require('nock');
const server = require('../server');
const request = require('request');
describe('My test', () =>{
it('Should returns the customized header', () => {
nock('url')
.get('/test')
.reply(302, {
'user-agent': 'Mozilla'
})
const { headers } = await request(server).get('/test');
expect(headers['user-agent']).to.include('Mozilla');
}
})
When I run the test, it fails and the log of headers received by request is like that:
{
'user-agent': 'node-superagent/3.8.3',
location: 'undefined',
vary: 'Accept, Accept-Encoding',
'content-type': 'text/plain; charset=utf-8',
'content-length': '31',
date: 'Fri, 24 May 2019 09:15:46 GMT',
connection: 'close'
}
Do I missed something or it's the normal behaviour of Nock?
The issue is with the way you're passing the headers to the reply function. Headers are the third argument for that method, but you're providing them as the second arg which means the object with the the user-agent key is being used as the body. Since it's a 302 and you probably want an empty body, you should pass an empty string as the second arg.
nock('url')
.get('/test')
.reply(302, '', {
'user-agent': 'Mozilla'
})
Related docs.
Related
I need to use http internal NodeJS library to make a POST request, how can i attach body object with this request? When I'm looking into http.RequestOptions I don't see any data or body property :/
import * as http from "http";
const options2: http.RequestOptions = {
hostname: 'www.google.com',
port: 80,
path: '/upload',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(null)
},
};
http.request(options, (res: http.IncomingMessage) => {
});
thanks for any help!
http.request returns an http.ClientRequest object.
You need to call the write method on that and pass in your body data.
Even though this question is asked several times at SO like:
fetch: Getting cookies from fetch response
or
Unable to set cookie in browser using request and express modules in NodeJS
None of this solutions could help me getting the cookie from a fetch() response
My setup looks like this:
Client
export async function registerNewUser(payload) {
return fetch('https://localhost:8080/register',
{
method: 'POST',
body: JSON.stringify(payload),
credentials: 'same-origin',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
}
});
}
...
function handleSubmit(e) {
e.preventDefault();
registerNewUser({...values, avatarColor: generateAvatarColor()}).then(response => {
console.log(response.headers.get('Set-Cookie')); // null
console.log(response.headers.get('cookie')); //null
console.log(document.cookie); // empty string
console.log(response.headers); // empty headers obj
console.log(response); // response obj
}).then(() => setValues(initialState))
}
server
private setUpMiddleware() {
this.app.use(cookieParser());
this.app.use(bodyParser.urlencoded({extended: true}));
this.app.use(bodyParser.json());
this.app.use(cors({
credentials: true,
origin: 'http://localhost:4200',
optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204
credentials: true
}));
this.app.use(express.static(joinDir('../web/build')));
}
...
this.app.post('/register', (request, response) => {
const { firstName, lastName, avatarColor, email, password }: User = request.body;
this.mongoDBClient.addUser({ firstName, lastName, avatarColor, email, password } as User)
.then(() => {
const token = CredentialHelper.JWTSign({email}, `${email}-${new Date()}`);
response.cookie('token', token, {httpOnly: true}).sendStatus(200); // tried also without httpOnly
})
.catch(() => response.status(400).send("User already registered."))
})
JavaScript fetch method won't send client side cookies and silently ignores the cookies sent from Server side Reference link in MDN, so you may use XMLHttpRequest method to send the request from your client side.
I figured it out. The solution was to set credentials to 'include' like so:
export async function registerNewUser(payload) {
return fetch('https://localhost:8080/register',
{
method: 'POST',
body: JSON.stringify(payload),
credentials: 'include',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
}
});
}
After that I needed to enabled credentials in my cors middleware:
this.app.use(cors({
credentials: true, // important part here
origin: 'http://localhost:4200',
optionsSuccessStatus: 200
})
And then finally I needed to remove the option {httpOnly: true} in the express route response:
response.cookie('token', '12345ssdfsd').sendStatus(200);
Keep in mind if you send the cookie like this, it is set directly to the clients cookies. You can now see that the cookie is set with: console.log(document.cookie).
But in a practical environment you don't want to send a cookie that is accessible by the client. You should usually use the {httpOnly: true} option.
I am trying to fetch the call status of a grandstream phone by a nodejs script. But I've run in some trouble. The first request is going all fine, and returning that I am authenticated. The second request isn't going well, it says that I'm not authenticated.
How do I set the credentials or the cookie from the first request in the second request, so it knows that I'm loggedin?
First request response:
Response=Success
Message=Authentication accepted
Needchange=0
Ver=1.0.3.92
First request response headers:
{
'status': '200',
'content-length': '79',
'content-location': 'http://192.168.0.1/manager?action=login&username=XXXXXX&secret=XXXXXX',
'set-cookie': 'phonecookie="XXXXXX";HttpOnly, type=admin;, Version="1";, Max-Age=900',
'server': 'Enterprise Phone',
'pragma': 'no-cache',
'cache-control': 'no-cache',
'date': 'Wed, 14 Jun 2017 10:22:29 GMT',
'content-type': 'text/plain'
}
Second request response:
Response=Error
Message=Authentication Required
App.js Script:
var fetch = require('node-fetch');
var host = '192.168.0.1';
var loginUrl = "/manager?action=login&username=XXXXXX&secret=XXXXXX";
var statusUrl = "/manager?action=lineStatus&line=0";
function makeRequest(url)
{
fetch("http://" + host + loginUrl).then(function(resultLogin) {
var resultAuth = result.body();
fetch("http://" + host + statusUrl, {method: 'GET').then(function(resultStatus) {
var resultStatus = resultStatus.body();
});
});
}
makeRequest();
Use fetch-cookie to let node-fetch store and send back cookies according to the url.
var fetch = require('fetch-cookie')(require('node-fetch'))
I'm trying to send an email but it isn't going through.
I used your example on README and also used the non Helper method one but none of them seems to work.
import { mail } from 'sendgrid';
const helper = mail;
const from_email = new helper.Email('admin#test.com');
const to_email = new helper.Email('someuser#test.com');
const subject = 'Testing';
const content = new helper.Content('text/plain', 'Test Description');
const email = new helper.Mail(from_email, subject, to_email, content);
const sg = require('sendgrid')(process.env.SENDGRID_API_KEY);
const request = sg.emptyRequest({
method: 'POST',
path: '/v3/mail/send',
body: email.toJSON()
});
sg.API(request, function(error, response) {
console.log(response.statusCode);
console.log(response.body);
console.log(response.headers);
});
The first console.log spits out the statusCode of 202.
The second console.log spits out nothing.
The last console.log spits out this:
{
server: 'nginx',
date: 'Mon, 15 Aug 2016 08:59:42 GMT',
'content-type': 'text/plain; charset=utf-8',
'content-length': '0',
connection: 'close',
'x-message-id': 'kQdayBbvSKSb9ZlVDCUKTg',
'x-frame-options': 'DENY'
}
For anyone having similar issue.
My account was apparently deactivated as I hadn't logged in to answer their support query. So what you need to do is to contact their support team.
I have an application build with koa and koa-router. When testing routes with supertest I face a problem, that content-type response header is always application/json; charset=utf-8.
const app = koa();
router
.get('/img', function *(next) {
this.type = 'image/png';
// this.set('Content-Type', 'image/png');
// this.set('content-type', 'image/png');
this.body = renderImage();
});
app
.use(router.routes())
.use(router.allowedMethods());
describe('Routes', () => {
it('should handle /tiles/*/*/*/* requests', (done) => {
request(http.createServer(app.callback()))
.get('/img')
.expect(200)
.expect('Content-Type', 'image/png')
.end(function (err, res) {
console.log(res.res.headers);
if (err) return done(err);
expect(renderImage).to.be.called;
done();
});
});
How test fails:
Error: expected "Content-Type" of "image/png", got "application/json; charset=utf-8"
at Test._assertHeader (node_modules/supertest/lib/test.js:215:12)
at Test._assertFunction (node_modules/supertest/lib/test.js:247:11)
at Test.assert (node_modules/supertest/lib/test.js:148:18)
at Server.assert (node_modules/supertest/lib/test.js:127:12)
at emitCloseNT (net.js:1525:8)
What is logged via console.log(res.res.headers):
{ 'content-type': 'application/json; charset=utf-8',
'content-length': '2',
date: 'Wed, 09 Mar 2016 10:15:37 GMT',
connection: 'close' }
Yet, if I do a request from the browser to the provided route, content-type header is changed correctly:
Connection:keep-alive
Content-Length:334
Content-Type:image/png
Date:Wed, 09 Mar 2016 10:15:01 GMT
Neither this.set('Content-Type', 'image/png'); nor this.set('content-type', 'image/png'); changes the situation.
Is it a bug? Has anyone faced the same issue?
A couple things to try:
Is this.body = renderImage() actually setting the body to null or undefined?
When looking through the Koa.js code for the response object, it looks like koa is removing the content-type header if the body is set to null or undefined.
Is the return value of renderImage() an object? If so, is it a buffer or stream? When the body is set koa tries to detect what the content-typeof the response should be. If it is not a string, Buffer, or stream, koa forces the content-type header to be application/json.