Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attach file gives 400 bad request #111

Closed
10kresources opened this issue Aug 22, 2016 · 10 comments
Closed

Attach file gives 400 bad request #111

10kresources opened this issue Aug 22, 2016 · 10 comments

Comments

@10kresources
Copy link

var file_path = '../data/invalid.csv';

chai.request(config.baseUrl)
.put(url)
.set('Accept', 'application/json')
.set('Content-Type', 'customHeader')
.attach('file', fs.readFileSync(file_path))
.end(function (err, res) {
res.should.have.status(500);
done();
});

I am expecting a 500 response (not here to argue, that's a good way to do things or not, it's a requirement, that I have to test) but I am getting 400

Testing the same manually (using POSTMAN) works just fine.

Any resolution will be highly appreciated. I am kinda blocked on this one..

@keithamus
Copy link
Member

Hey @coolnixy thanks for the issue.

I believe the problem you're seeing is because attach (see SuperAgent source) uses FormData - this module changes the Content-Type header. I think you might find that by the time your request is made, the Content-Type header is no longer customHeader but some other value.

The fix could be to try setting Content-Type after attach - to illustrate:

var file_path = '../data/invalid.csv';

chai.request(config.baseUrl)
.put(url)
.attach('file', fs.readFileSync(file_path))
.set('Accept', 'application/json')
.set('Content-Type', 'customHeader')
.end(function (err, res) {
  res.should.have.status(500);
  done();
});

@10kresources
Copy link
Author

Thanks @keithamus for your response. I tried your suggestion, but didn't work for me :( Any other way I can get this working?

@keithamus
Copy link
Member

@coolnixy could you please provide more information, or perhaps write a reduced test case?

If you console.log(res) what comes back?

@10kresources
Copy link
Author

@keithamus Thanks for responding.. I am getting message "The request is invalid" in result. What you mentioned on your first comment is correct. The custom header is not passed. Is there a way we can attach the file as binary and let the custom header be there?

@keithamus
Copy link
Member

@coolnixy can you please provide the full output of res - I'm interested in seeing what the initial request headers were (which are attached to the res object).

@10kresources
Copy link
Author

10kresources commented Aug 25, 2016

@keithamus here is the full output..

Upload claims tests

Upload claims tests
Response {
domain: null,
_events: {},
_eventsCount: 0,
_maxListeners: undefined,
res:
IncomingMessage {
_readableState:
ReadableState {
objectMode: false,
highWaterMark: 16384,
buffer: [],
length: 0,
pipes: null,
pipesCount: 0,
flowing: true,
ended: true,
endEmitted: true,
reading: false,
sync: true,
needReadable: false,
emittedReadable: false,
readableListening: false,
resumeScheduled: false,
defaultEncoding: 'utf8',
ranOut: false,
awaitDrain: 0,
readingMore: false,
decoder: [Object],
encoding: 'utf8' },
readable: false,
domain: null,
_events:
{ end: [Object],
data: [Object],
error: [Object],
close: [Function: bound emit] },
_eventsCount: 4,
_maxListeners: undefined,
socket:
TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: null,
npnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object],
_eventsCount: 9,
_connecting: false,
_hadError: false,
_handle: null,
_parent: null,
_host: 'dev.test.xyz.com',
_readableState: [Object],
readable: false,
domain: null,
_maxListeners: undefined,
_writableState: [Object],
writable: false,
allowHalfOpen: false,
destroyed: true,
_bytesDispatched: 1261,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: null,
_requestCert: true,
_rejectUnauthorized: true,
parser: null,
_httpMessage: [Object],
read: [Function],
_consuming: true,
_idleNext: null,
_idlePrev: null,
_idleTimeout: -1 },
connection:
TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: null,
npnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object],
_eventsCount: 9,
_connecting: false,
_hadError: false,
_handle: null,
_parent: null,
_host: 'dev.test.xyz.com',
_readableState: [Object],
readable: false,
domain: null,
_maxListeners: undefined,
_writableState: [Object],
writable: false,
allowHalfOpen: false,
destroyed: true,
_bytesDispatched: 1261,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: null,
_requestCert: true,
_rejectUnauthorized: true,
parser: null,
_httpMessage: [Object],
read: [Function],
_consuming: true,
_idleNext: null,
_idlePrev: null,
_idleTimeout: -1 },
httpVersionMajor: 1,
httpVersionMinor: 1,
httpVersion: '1.1',
complete: true,
headers:
{ 'content-type': 'application/json; charset=utf-8',
'content-length': '37',
connection: 'close',
'cache-control': 'no-cache',
date: 'Thu, 25 Aug 2016 01:05:54 GMT',
expires: '-1',
pragma: 'no-cache',
server: 'Microsoft-IIS/8.5',
'x-aspnet-version': '4.0.30319',
'x-powered-by': 'ASP.NET',
'x-cache': 'Error from cloudfront',
via: '1.1 74b217f6de96253e0ed5551fd50bc165.cloudfront.net (CloudFront)',
'x-amz-cf-id': 'fLY_xt3DkMi7wSMbxl3CnL8QaGSFU05QHKA5pRgDMriBTPJD39BiNA==' },
rawHeaders:
[ 'Content-Type',
'application/json; charset=utf-8',
'Content-Length',
'37',
'Connection',
'close',
'Cache-Control',
'no-cache',
'Date',
'Thu, 25 Aug 2016 01:05:54 GMT',
'Expires',
'-1',
'Pragma',
'no-cache',
'Server',
'Microsoft-IIS/8.5',
'X-AspNet-Version',
'4.0.30319',
'X-Powered-By',
'ASP.NET',
'X-Cache',
'Error from cloudfront',
'Via',
'1.1 74b217f6de96253e0ed5551fd50bc165.cloudfront.net (CloudFront)',
'X-Amz-Cf-Id',
'fLY_xt3DkMi7wSMbxl3CnL8QaGSFU05QHKA5pRgDMriBTPJD39BiNA==' ],
trailers: {},
rawTrailers: [],
upgrade: false,
url: '',
method: null,
statusCode: 400,
statusMessage: 'Bad Request',
client:
TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: null,
npnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object],
_eventsCount: 9,
_connecting: false,
_hadError: false,
_handle: null,
_parent: null,
_host: 'dev.test.xyz.com',
_readableState: [Object],
readable: false,
domain: null,
_maxListeners: undefined,
_writableState: [Object],
writable: false,
allowHalfOpen: false,
destroyed: true,
_bytesDispatched: 1261,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: null,
_requestCert: true,
_rejectUnauthorized: true,
parser: null,
_httpMessage: [Object],
read: [Function],
_consuming: true,
_idleNext: null,
_idlePrev: null,
_idleTimeout: -1 },
_consuming: true,
_dumped: false,
req:
ClientRequest {
domain: null,
_events: [Object],
_eventsCount: 3,
_maxListeners: undefined,
output: [],
outputEncodings: [],
outputCallbacks: [],
outputSize: 0,
writable: true,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedHeader: [Object],
_contentLength: null,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket: [Object],
connection: [Object],
_header: 'PUT /api/full/path HTTP/1.1\r\nHost: dev.test.xyz.com\r\nAccept-Encoding: gzip, deflate\r\nUser-Agent: node-superagent/2.1.0\r
Authorization: Bearer 377a0920a304cf040b7258fc9481eb84\r\nAccept: application/json\r\ncontent-type: multipart/form-data
boundary=--------------------------276293373713535782110304\r\nContent-Length: 827\r\nConnection: close\r\n\r\n',
_headers: [Object],
_headerNames: [Object],
_onPendingData: null,
agent: [Object],
socketPath: undefined,
method: 'PUT',
path: '/api/full/path',
parser: null,
res: [Circular] },
text: '{"message":"The request is invalid."}',
read: [Function],
body: { message: 'The request is invalid.' } },
request:
Test {
domain: null,
_events: { end: [Function: bound _clearTimeout] },
_eventsCount: 1,
_maxListeners: undefined,
_agent: false,
_formData:
FormData {
_overheadLength: 171,
_valueLength: 600,
_lengthRetrievers: [],
writable: false,
readable: true,
dataSize: 0,
maxDataSize: 2097152,
pauseStreams: true,
_released: true,
_streams: [],
_currentStream: null,
_events: [Object],
_eventsCount: 1,
_boundary: '--------------------------276293373713535782110304' },
method: 'put',
url: 'https://dev.test.xyz.com/api/full/path',
_header:
{ 'user-agent': 'node-superagent/2.1.0',
authorization: 'Bearer 377a0920a304cf040b7258fc9481eb84',
accept: 'application/json',
'content-type': 'application/vnd+xyz.bulkclaim.abc+csv' },
header:
{ 'User-Agent': 'node-superagent/2.1.0',
Authorization: 'Bearer 377a0920a304cf040b7258fc9481eb84',
Accept: 'application/json',
'Content-Type': 'application/vnd+xyz.bulkclaim.abc+csv' },
writable: true,
_redirects: 0,
_maxRedirects: 5,
cookies: '',
qs: {},
qsRaw: [],
_redirectList: [],
_streamRequest: false,
app: 'https://dev.test.xyz.com',
req:
ClientRequest {
domain: null,
_events: [Object],
_eventsCount: 3,
_maxListeners: undefined,
output: [],
outputEncodings: [],
outputCallbacks: [],
outputSize: 0,
writable: true,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedHeader: [Object],
_contentLength: null,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket: [Object],
connection: [Object],
_header: 'PUT /api/full/path HTTP/1.1\r\nHost: dev.test.xyz.com\r\nAccept-Encoding: gzip, deflate\r\nUser-Agent: node-superagent/2.1.0\r
Authorization: Bearer 377a0920a304cf040b7258fc9481eb84\r\nAccept: application/json\r\ncontent-type: multipart/form-data
boundary=--------------------------276293373713535782110304\r\nContent-Length: 827\r\nConnection: close\r\n\r\n',
_headers: [Object],
_headerNames: [Object],
_onPendingData: null,
agent: [Object],
socketPath: undefined,
method: 'PUT',
path: '/api/full/path',
parser: null,
res: [Object] },
protocol: 'https:',
host: 'dev.test.xyz.com',
_callback: [Function],
res:
IncomingMessage {
_readableState: [Object],
readable: false,
domain: null,
_events: [Object],
_eventsCount: 4,
_maxListeners: undefined,
socket: [Object],
connection: [Object],
httpVersionMajor: 1,
httpVersionMinor: 1,
httpVersion: '1.1',
complete: true,
headers: [Object],
rawHeaders: [Object],
trailers: {},
rawTrailers: [],
upgrade: false,
url: '',
method: null,
statusCode: 400,
statusMessage: 'Bad Request',
client: [Object],
_consuming: true,
_dumped: false,
req: [Object],
text: '{"message":"The request is invalid."}',
read: [Function],
body: [Object] },
_timeout: 0,
response: [Circular],
called: true },
req:
ClientRequest {
domain: null,
_events: { drain: [Object], error: [Object], response: [Function] },
_eventsCount: 3,
_maxListeners: undefined,
output: [],
outputEncodings: [],
outputCallbacks: [],
outputSize: 0,
writable: true,
_last: true,
chunkedEncoding: false,
shouldKeepAlive: false,
useChunkedEncodingByDefault: true,
sendDate: false,
_removedHeader: { 'content-length': false },
_contentLength: null,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket:
TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: null,
npnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object],
_eventsCount: 9,
_connecting: false,
_hadError: false,
_handle: null,
_parent: null,
_host: 'dev.test.xyz.com',
_readableState: [Object],
readable: false,
domain: null,
_maxListeners: undefined,
_writableState: [Object],
writable: false,
allowHalfOpen: false,
destroyed: true,
_bytesDispatched: 1261,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: null,
_requestCert: true,
_rejectUnauthorized: true,
parser: null,
_httpMessage: [Circular],
read: [Function],
_consuming: true,
_idleNext: null,
_idlePrev: null,
_idleTimeout: -1 },
connection:
TLSSocket {
_tlsOptions: [Object],
_secureEstablished: true,
_securePending: false,
_newSessionPending: false,
_controlReleased: true,
_SNICallback: null,
servername: null,
npnProtocol: false,
authorized: true,
authorizationError: null,
encrypted: true,
_events: [Object],
_eventsCount: 9,
_connecting: false,
_hadError: false,
_handle: null,
_parent: null,
_host: 'dev.test.xyz.com',
_readableState: [Object],
readable: false,
domain: null,
_maxListeners: undefined,
_writableState: [Object],
writable: false,
allowHalfOpen: false,
destroyed: true,
_bytesDispatched: 1261,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: undefined,
_server: null,
ssl: null,
_requestCert: true,
_rejectUnauthorized: true,
parser: null,
_httpMessage: [Circular],
read: [Function],
_consuming: true,
_idleNext: null,
_idlePrev: null,
_idleTimeout: -1 },
_header: 'PUT /api/full/path
HTTP/1.1\r\nHost: dev.test.xyz.com\r\nAccept-Encoding: gzip, deflate\r\nUser-Agent: node-superagent/2.1.0\r\nAu
horization: Bearer 377a0920a304cf040b7258fc9481eb84\r\nAccept: application/json\r\ncontent-type: multipart/form-data; b
undary=--------------------------276293373713535782110304\r\nContent-Length: 827\r\nConnection: close\r\n\r\n',
_headers:
{ host: 'dev.test.xyz.com',
'accept-encoding': 'gzip, deflate',
'user-agent': 'node-superagent/2.1.0',
authorization: 'Bearer 377a0920a304cf040b7258fc9481eb84',
accept: 'application/json',
'content-type': 'multipart/form-data; boundary=--------------------------276293373713535782110304',
'content-length': 827 },
_headerNames:
{ host: 'Host',
'accept-encoding': 'Accept-Encoding',
'user-agent': 'User-Agent',
authorization: 'Authorization',
accept: 'Accept',
'content-type': 'content-type',
'content-length': 'Content-Length' },
_onPendingData: null,
agent:
Agent {
domain: null,
_events: [Object],
_eventsCount: 1,
_maxListeners: undefined,
defaultPort: 443,
protocol: 'https:',
options: [Object],
requests: {},
sockets: [Object],
freeSockets: {},
keepAliveMsecs: 1000,
keepAlive: false,
maxSockets: Infinity,
maxFreeSockets: 256,
maxCachedSessions: 100,
_sessionCache: [Object] },
socketPath: undefined,
method: 'PUT',
path: '/api/full/path',
parser: null,
res:
IncomingMessage {
_readableState: [Object],
readable: false,
domain: null,
_events: [Object],
_eventsCount: 4,
_maxListeners: undefined,
socket: [Object],
connection: [Object],
httpVersionMajor: 1,
httpVersionMinor: 1,
httpVersion: '1.1',
complete: true,
headers: [Object],
rawHeaders: [Object],
trailers: {},
rawTrailers: [],
upgrade: false,
url: '',
method: null,
statusCode: 400,
statusMessage: 'Bad Request',
client: [Object],
_consuming: true,
_dumped: false,
req: [Circular],
text: '{"message":"The request is invalid."}',
read: [Function],
body: [Object] } },
links: {},
text: '{"message":"The request is invalid."}',
body: { message: 'The request is invalid.' },
files: undefined,
buffered: true,
headers:
{ 'content-type': 'application/json; charset=utf-8',
'content-length': '37',
connection: 'close',
'cache-control': 'no-cache',
date: 'Thu, 25 Aug 2016 01:05:54 GMT',
expires: '-1',
pragma: 'no-cache',
server: 'Microsoft-IIS/8.5',
'x-aspnet-version': '4.0.30319',
'x-powered-by': 'ASP.NET',
'x-cache': 'Error from cloudfront',
via: '1.1 74b217f6de96253e0ed5551fd50bc165.cloudfront.net (CloudFront)',
'x-amz-cf-id': 'fLY_xt3DkMi7wSMbxl3CnL8QaGSFU05QHKA5pRgDMriBTPJD39BiNA==' },
header:
{ 'content-type': 'application/json; charset=utf-8',
'content-length': '37',
connection: 'close',
'cache-control': 'no-cache',
date: 'Thu, 25 Aug 2016 01:05:54 GMT',
expires: '-1',
pragma: 'no-cache',
server: 'Microsoft-IIS/8.5',
'x-aspnet-version': '4.0.30319',
'x-powered-by': 'ASP.NET',
'x-cache': 'Error from cloudfront',
via: '1.1 74b217f6de96253e0ed5551fd50bc165.cloudfront.net (CloudFront)',
'x-amz-cf-id': 'fLY_xt3DkMi7wSMbxl3CnL8QaGSFU05QHKA5pRgDMriBTPJD39BiNA==' },
statusCode: 400,
status: 400,
statusType: 4,
info: false,
ok: false,
redirect: false,
clientError: true,
serverError: false,
error:
{ [Error: cannot PUT /api/full/path (400)]
status: 400,
text: '{"message":"The request is invalid."}',
method: 'PUT',
path: /api/full/path' },
accepted: false,
noContent: false,
badRequest: true,
unauthorized: false,
notAcceptable: false,
forbidden: false,
notFound: false,
charset: 'utf-8',
type: 'application/json',
setEncoding: [Function: bound ],
redirects: [] }

@keithamus
Copy link
Member

@coolnixy yeah see it is changing the request header's content type to content-type: multipart/form-data; boundary=--------------------------276293373713535782110304.

The way to fix that should be overriding the header after attach() runs. If that doesn't work then I'm not sure how much more I can help I'm afraid.

@10kresources
Copy link
Author

Thanks @keithamus . I will try to override the header and see if it works. Will update you, if it works!! Thanks for your help thus far!. Appreciated.

@meeber
Copy link
Contributor

meeber commented Dec 15, 2016

@coolnixy Gonna close this issue due to no updates in a few months. Please feel welcome to reopen it if there's still an issue!

@meeber meeber closed this as completed Dec 15, 2016
@vaibhavpuri
Copy link

I am also facing a similar problem: https://stackoverflow.com/questions/46204374/chai-http-attach-sets-up-content-type-multipart-formdata
so basically i am trying to post a file as binary since my method accepts the image as binary, so trying to set the content type to image/jpeg after attach:

chai.request('http://localhost:8085')
.post('/myAPI/' + req.params.id + '/logo')
.attach('image', fs.readFileSync(__dirname + '/resources/IMG_86425.jpg'), 'IMG_86425.jpg')
.set('Content-Type','image/jpeg')
.end((err, res) => {
should.equal(err, null);
res.status.should.equal(200);
res.should.be.json;
done();
});

Still when i log the request content type in the code i see req.contentType : multipart/form-data
Is there a work around for this OR is there any other way i can post a binary through chai http.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants