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

Set Authorization header to post request #398

Closed
ghost opened this issue Jan 25, 2017 · 28 comments
Closed

Set Authorization header to post request #398

ghost opened this issue Jan 25, 2017 · 28 comments

Comments

@ghost
Copy link

ghost commented Jan 25, 2017

  1. Request:
request(app)
      .post('/api/categories')
      .send(category)
      .set({ Authorization: token })
      .end((err, res) => {
        const newCategory = res.body;

        expect(res.status).to.be.equal(200);
        expect(newCategory).to.be.equal(category);

        done();
      });

Error:
Error: "value" required in setHeader("Authorization", value)

  1. Request:
request(app)
      .post('/api/categories')
      .send(category)
      .setHeader('Authorization', token)
      .end((err, res) => {
        const newCategory = res.body;

        expect(res.status).to.be.equal(200);
        expect(newCategory).to.be.equal(category);

        done();
      });

Error:
TypeError: (0 , _supertest2.default)(...).post(...).send(...).setHeader is not a function

How set header to post request ?

@mikelax
Copy link
Contributor

mikelax commented Jan 29, 2017

You do want to use the .set function.
You should be able to pass a single JSON object or two parameters for the key and value.

.set('Accept', 'application/json')
.set({ 'API-Key': 'foobar', Accept: 'application/json' })

In your first example I would say that there is a problem with the variable token.

@mikelax mikelax closed this as completed Jan 29, 2017
@IvanCaro
Copy link

IvanCaro commented Sep 3, 2017

this does not work.

@gilbert
Copy link

gilbert commented Feb 17, 2018

Note that you have to call .set() AFTER calling .post(), not before. For example:

request(app)
  .set('Authorization', 'abc123') // DOES NOT WORK
  .post('/api')

request(app)
  .post('/api')
  .set('Authorization', 'abc123') // Works.

@JafarAkhondali
Copy link

Note that you have to call .set() AFTER calling .post(), not before. For example:

request(app)
  .set('Authorization', 'abc123') // DOES NOT WORK
  .post('/api')

request(app)
  .post('/api')
  .set('Authorization', 'abc123') // Works.

It's TERRIBLE !!!
Suppose i have multiple routes to test, which all are protected by same authentication middleware ( using headers). This way, I have to set header independently for all of them!!

@thelebdev
Copy link

Note that you have to call .set() AFTER calling .post(), not before. For example:

request(app)
  .set('Authorization', 'abc123') // DOES NOT WORK
  .post('/api')

request(app)
  .post('/api')
  .set('Authorization', 'abc123') // Works.

It's TERRIBLE !!!
Suppose i have multiple routes to test, which all are protected by same authentication middleware ( using headers). This way, I have to set header independently for all of them!!

Well it would only make sense to do that since in a real-life scenario you are making separate HTTP Requests, each having its own separate Header. Unless I understood you wrong?

@JafarAkhondali
Copy link

JafarAkhondali commented Aug 2, 2019

@christopheelkhoury In a real-life app, i would set auth header in state and create a new instance of HttpRequest which hold the auth header. For example this is my HttpService:


export default () => {
  return axios.create({
    baseURL: `${config.BASE_URL}/${config.API_VERSION}`,
    headers: {
      'blog-admin': store.state.Auth.token || '',
      'Cache-Control': 'no-cache'
    }
  })
}

And i'll call it like:

export function index() {
  return Http().get('/posts')
}

So there is no duplication of code and i can change header or auth method easily by changing one line of code. But the syntax in super test makes me to set header separately for each request which is not clean and not DRY

@Rupeshiya
Copy link

Rupeshiya commented Sep 10, 2019

@JafarAkhondali If you are talking about setting up the header for multiple routes then you can do something like make function which will execute before all the test case and freom there get that header value and set it in others routes so in that way you dont have to write the same request code all the time whereas only thing you have to do is to set the value using .set('Authorization', value)

Example: -

var loggedInToken = '';
before((done)=>{
    chai.request(server)
    .post('/api/users/login')
    .send({
      email: email,
      password: password
    })
    .end((err, response)=>{
      loggedInToken = response.body.token;
      done();
    });
  });

now use that set() in all the routes
Hope this helps.

@vegaByte
Copy link

vegaByte commented Apr 1, 2020

Separe the request logic from all your tests simulating supertest(url).method()

const URL = `My Endpoint`;
const TOKEN = 'Secret';

const hook = (method = 'post') => (args) =>
  supertest(URL)
    [method](args)
    .set('Authorization', `Basic ${TOKEN}`);

const request = {
  post: hook('post'),
  get: hook('get'),
  put: hook('put'),
  delete: hook('delete'),
};

export default request;

I dont touch my tests code

@AndonMitev
Copy link

AndonMitev commented Dec 17, 2020

I'm trying to set header but is not part of the headers

 await request(app)
            .get('/user/all')
            .set({
                Authorization: 'abc123',
            })
            .expect(({ headers }) => {
                console.log(headers);
            })
            .expect(HttpStatus.BAD_REQUEST);

This is the headers object:

 {
      'content-security-policy': "default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests",
      'x-dns-prefetch-control': 'off',
      'expect-ct': 'max-age=0',
      'x-frame-options': 'SAMEORIGIN',
      'strict-transport-security': 'max-age=15552000; includeSubDomains',
      'x-download-options': 'noopen',
      'x-content-type-options': 'nosniff',
      'x-permitted-cross-domain-policies': 'none',
      'referrer-policy': 'no-referrer',
      'x-xss-protection': '0',
      'access-control-allow-origin': '*',
      'content-type': 'application/json; charset=utf-8',
      'content-length': '43',
      etag: 'W/"2b-hGShxOkieaAVDloBubJVM+h58D8"',
      date: 'Thu, 17 Dec 2020 11:07:30 GMT',
      connection: 'close'
    }

Any idea how to append Authorization to the headers?

I also tried .set(Authorization, 'abc123')

@thelebdev
Copy link

I'm trying to set header but is not part of the headers

 await request(app)
            .get('/user/all')
            .set({
                Authorization: 'abc123',
            })
            .expect(({ headers }) => {
                console.log(headers);
            })
            .expect(HttpStatus.BAD_REQUEST);

This is the headers object:

 {
      'content-security-policy': "default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests",
      'x-dns-prefetch-control': 'off',
      'expect-ct': 'max-age=0',
      'x-frame-options': 'SAMEORIGIN',
      'strict-transport-security': 'max-age=15552000; includeSubDomains',
      'x-download-options': 'noopen',
      'x-content-type-options': 'nosniff',
      'x-permitted-cross-domain-policies': 'none',
      'referrer-policy': 'no-referrer',
      'x-xss-protection': '0',
      'access-control-allow-origin': '*',
      'content-type': 'application/json; charset=utf-8',
      'content-length': '43',
      etag: 'W/"2b-hGShxOkieaAVDloBubJVM+h58D8"',
      date: 'Thu, 17 Dec 2020 11:07:30 GMT',
      connection: 'close'
    }

Any idea how to append Authorization to the headers?

I also tried .set(Authorization, 'abc123')

@AndonMitev I'm guessing you're using the request package.
If that's the case, I'd recommend you construct the request object before sending it, making your code as such:

const options = {
  uri: <YOUR_URL>,
  method: 'GET',
  headers: {
    'Auhorization': 'Bearer <TOKEN>'
  }
};
await request(options)
            .expect(({ headers }) => {
                console.log(headers);
            })
            .expect(HttpStatus.BAD_REQUEST);

@ekramteyeb
Copy link

I'm trying to set header but is not part of the headers

 await request(app)
            .get('/user/all')
            .set({
                Authorization: 'abc123',
            })
            .expect(({ headers }) => {
                console.log(headers);
            })
            .expect(HttpStatus.BAD_REQUEST);

This is the headers object:

 {
      'content-security-policy': "default-src 'self';base-uri 'self';block-all-mixed-content;font-src 'self' https: data:;frame-ancestors 'self';img-src 'self' data:;object-src 'none';script-src 'self';script-src-attr 'none';style-src 'self' https: 'unsafe-inline';upgrade-insecure-requests",
      'x-dns-prefetch-control': 'off',
      'expect-ct': 'max-age=0',
      'x-frame-options': 'SAMEORIGIN',
      'strict-transport-security': 'max-age=15552000; includeSubDomains',
      'x-download-options': 'noopen',
      'x-content-type-options': 'nosniff',
      'x-permitted-cross-domain-policies': 'none',
      'referrer-policy': 'no-referrer',
      'x-xss-protection': '0',
      'access-control-allow-origin': '*',
      'content-type': 'application/json; charset=utf-8',
      'content-length': '43',
      etag: 'W/"2b-hGShxOkieaAVDloBubJVM+h58D8"',
      date: 'Thu, 17 Dec 2020 11:07:30 GMT',
      connection: 'close'
    }

Any idea how to append Authorization to the headers?

I also tried .set(Authorization, 'abc123')

// if you setup ur server to response with a token after a login operation u can authorize the get/post individual operation as follow .N.B // token = a string sent back as response header to the browser by a server
await request(app)

        .get('/user/all')
        .auth(token, {type:'bearer'} ) 
          
        })
        .expect(({ headers }) => {
            console.log(headers);

@junajan
Copy link

junajan commented Feb 23, 2021

Note that you have to call .set() AFTER calling .post(), not before. For example:

request(app)
  .set('Authorization', 'abc123') // DOES NOT WORK
  .post('/api')

request(app)
  .post('/api')
  .set('Authorization', 'abc123') // Works.

It's TERRIBLE !!!
Suppose i have multiple routes to test, which all are protected by same authentication middleware ( using headers). This way, I have to set header independently for all of them!!

Well it would only make sense to do that since in a real-life scenario you are making separate HTTP Requests, each having its own separate Header. Unless I understood you wrong?

Sometimes - eg while running integration tests - it completely makes sense to set same headers for all requests.
In my case I would like to create a factory method which returns supertest agent with default headers but because headers are reseted when .post() is called, it is not easily possible..

@felixmosh
Copy link

felixmosh commented Apr 6, 2021

It is possible by using the agent it self, and calling auth method, which defines a default set of headers

Calling agent.post will set these defaults

import { agent as supertest } from 'supertest';
// ---------^ this is the important part, using the agent itself.
import app from './app';

agent = supertest(app);
const response = await agent.post('/api/auth/login', { username: 'tester', password: 'tester' });
agent.auth(response.accessToken, { type: 'bearer' });

// this request will include the Authorization header
agent.post('/api/customer/add', { name: 'foo' });

@kamariana
Copy link

kamariana commented Jun 25, 2021

Peace, @vegaByte @felixmosh @thelebdev I have an internal server error with the following. Anyone knows why? Here is the repo https://github.com/camariana/fs-blog-list

`
test('succeeds with valid data', async () => {
const newBlog = {
title: 'What we are living for',
author: 'A. Camariana',
url: 'camariana.gm',
likes: 0,
}
await api
.post('/api/blogs/')
.set({ 'Authorization': 'bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImNhbWFyaWFuYSIsImlkIjoiNjBiYThjODQ0OWIzMjU0YWUzZDFiZDBmIiwiaWF0IjoxNjI0MzQ2Mjg4LCJleHAiOjE2MjQzNDk4ODh9.ruPKk293QDfxUq1emdVH0sbuJEhRrfY9q9jVllaMYPA' })
.send(newBlog)
.expect(200)
.expect('Content-Type', /application/json/)

const blogsAtEnd = await helper.blogsInDb()
expect(blogsAtEnd).toHaveLength(helper.initialBlogs.length + 1)

const contents = blogsAtEnd.map(b => b.title)
expect(contents).toContain(
  'What we are living for'
)

})
`

@kamariana
Copy link

Separe the request logic from all your tests simulating supertest(url).method()

const URL = `My Endpoint`;
const TOKEN = 'Secret';

const hook = (method = 'post') => (args) =>
  supertest(URL)
    [method](args)
    .set('Authorization', `Basic ${TOKEN}`);

const request = {
  post: hook('post'),
  get: hook('get'),
  put: hook('put'),
  delete: hook('delete'),
};

export default request;

I dont touch my tests code

@vegaByte, How do you go about implementing this?

@technoknol
Copy link

It is possible by using the agent it self, and calling auth method, which defines a default set of headers

Calling agent.post will set these defaults

import { agent as supertest } from 'supertest';
// ---------^ this is the important part, using the agent itself.
import app from './app';

agent = supertest(app);
const response = await agent.post('/api/auth/login', { username: 'tester', password: 'tester' });
agent.auth(response.accessToken, { type: 'bearer' });

// this request will include the Authorization header
agent.post('/api/customer/add', { name: 'foo' });

I'm getting this error:
image

Can anyone help here?

@mmamedel
Copy link

mmamedel commented May 18, 2022

Why not using Proxy? Such as:

const defaultAgent = new Proxy(supertest(app), {
  get: (target, name) => (…args) =>
    (target as any)[name](…args).set({
      'Authorization': `Bearer ${defaultToken}`,
      'Accept': 'application/json',
    }),
})

Then you can use just as any agent:

defaultAgent.get('url')
defaultAgent.post('url')
...

You can set any properties in the proxy.

@BugliL
Copy link

BugliL commented Apr 14, 2023

I have resolved with a simple monkey patching

// ...

    beforeAll(() => {
      request = supertest(app.getHttpServer());
      // Next line is important or recursion hell will kill your code
      const originalMethod = request.patch;
      request.patch = (url: string, ...args) => {
        return originalMethod(url, ...args)
          .set('Content-Type', 'application/json')
          .set('X_CONNECTION_KEY', 'XXX');
      };
    });
    
// ...

@marvin-wtt
Copy link

I noticed a strange behavior today with a delete request:

This works:

request(app)
  .delete(`/resource/${id}`)
  .set({ Authorization: `Bearer ${token}` })
  .expect(204); // Passes

But this does not work:

const response = await request(app)
  .delete(`/resource/${id}`)
  .set({ Authorization: `Bearer ${token}` });

expect(response.statusCode).toBe(204); // Fails --> 401

What is the problem here?

@felixmosh
Copy link

calling delete before the set will execute the request before you set the header.

@marvin-wtt
Copy link

calling delete before the set will execute the request before you set the header.

Thanks for your reply.
How is it possible to set a header before calling delete?

The example in the README uses the GET verb, but the call is very similar:

describe('GET /users', function() {
  it('responds with json', async function() {
    const response = await request(app)
      .get('/users')
      .set('Accept', 'application/json')
    expect(response.headers["Content-Type"]).toMatch(/json/);
    expect(response.status).toEqual(200);
    expect(response.body.email).toEqual('foo@bar.com');
  });
});

@techrook
Copy link

how can i set authorization for API KEY ?

@TinNguyenWav
Copy link

TinNguyenWav commented Jul 14, 2023

how can i set authorization for API KEY ?

Hopefully this can help you, @techrook

`
import supertest from "supertest"
import { REQRES_BASE_URI } from 'src/api/config/baseuri';
import { endpoints } from "src/api/services/endpoints";

const request = supertest(REQRES_BASE_URI)
const HEADER = {
TOKEN: process.env.API_KEY
}
const token = "Your token string"

export const makeGETCall = async (endpoint: endpoints | string) => {
return request.get(endpoint).set('Authorization', Bearer ${HEADER.TOKEN})
//OR
/*
return request.get(endpoint).set('Authorization', Bearer ${token})
*/
}
`

@adityadafe
Copy link

.env file

TOKEN = 'averylongstring'

case 1:

await api.post('/').set('Authorization ' ,'Bearer ${process.env.TOKEN') // this fails with 400 status code

case 2:

const token = 'averylongstring'
await api.post('/').set('Authorization ' ,'Bearer ${token') // this pass

why is this happening

@benistary
Copy link

await api.post('/').set('Authorization ' ,'Bearer ${process.env.TOKEN')

Because in case 1 you have wrong syntax. You are missing backtics `` and one bracket } It should be like this:

await api.post('/').set('Authorization ' ,`Bearer ${process.env.TOKEN}`)

@vedantjangid
Copy link

await api.post('/').set('Authorization ' ,'Bearer ${process.env.TOKEN')

Because in case 1 you have wrong syntax. You are missing backtics `` and one bracket } It should be like this:

await api.post('/').set('Authorization ' ,`Bearer ${process.env.TOKEN}`)

.set("Authorization", Bearer ${loginResponse.body.token}) // Corrected here

@lopes-gustavo
Copy link

lopes-gustavo commented Feb 22, 2024

Whoever come to this issue, there's a simpler way of doing this, using the underlying superagent

Instead of this (unfortunately it doesn't work)

request(app)
  .set('Authorization', 'abc123')
  .post('/api');

You can do

request.agent(app)
  .set('Authorization', 'abc123') // Using the superagent behind supertest
  .post('/api');

You can do even better if you export the server and reuse it across tests:

export const server = request.agent(app).set('Authorization', 'abc123');

//[...]

server.post('/api').expect(201);
server.get('/other-api').expect(200);

@karocksjoelee
Copy link

Why is this closed ?.?

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