Symfony functional test - custom headers not passing through
Asked Answered
S

3

42

For some reason when i sent a new $client->request the headers I specify get lost:

public function testGetClientsAction()
{
    $client = static::createClient();

    $cookie = new Cookie('locale2', 'en', time() + 3600 * 24 * 7, '/', null, false, false);
    $client->getCookieJar()->set($cookie);

    // Visit user login page and login
    $crawler = $client->request('GET', '/login');
    $form = $crawler->selectButton('login')->form();
    $crawler = $client->submit($form, array('_username' => 'greg', '_password' => 'greg'));

    $client->request(
       'GET', 
       '/clients', 
        array(), 
        array(), 
        array('X-Requested-With' => 'XMLHttpRequest', 'accept' => 'application/json')
    );

    print_r($client->getResponse());
    die();

}

In the method that is being tested I have this on the first line:

print_r($request->headers->all());

The response is as follows:

Array
(
    [host] => Array
        (
            [0] => localhost
        )

    [user-agent] => Array
        (
            [0] => Symfony2 BrowserKit
        )

    [accept] => Array
        (
            [0] => text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
        )

    [accept-language] => Array
        (
            [0] => en-us,en;q=0.5
        )

    [accept-charset] => Array
        (
            [0] => ISO-8859-1,utf-8;q=0.7,*;q=0.7
        )

    [referer] => Array
        (
            [0] => http://localhost/login_check
        )

    [x-php-ob-level] => Array
        (
            [0] => 1
        )

)
Status answered 18/7, 2012 at 20:24 Comment(0)
M
73

I have the same issue and after a little dig through I think it is a feature that BrowserKit currently doesn't support.

I have logged an issue for it: https://github.com/symfony/symfony/issues/5074

Update: this is not an issue -- see the comments below

Sample Code

Sample request:

$client->request(
    'GET',
    $url,
    array(),
    array(),
    array(
        'HTTP_X_CUSTOM_VAR' => $var
    )
);

Fetching the data:

$request->headers->get('x-custom-var');
Malefaction answered 27/7, 2012 at 4:25 Comment(6)
Update: from a comment I got from stof in the issue, just pass a variation of your custom header by prefixing it with "HTTP_" and it will works. See the above issue for an working example in my case.Malefaction
Good stuff. Thanks for your help!Status
This is not the case anymore (sym2.5) - header without a prefix is fine! Check symfony.com/doc/current/book/testing.html for exampleWrens
@Wrens is only partially right. custom headers will work only with "HTTP_" prefix while standard header keys will work without.Blanchette
Still a valid response after all this time. What's the rationale behind this decision? Seems absurd.Regalado
notice the difference you pass _ but then you read with -Sewel
M
22

If you check the definition from Client.php, at method request, you will see in the docblock a very useful information:

  • @param array $server The server parameters (HTTP headers are referenced with a HTTP_ prefix as PHP does)

This means that you should add a HTTP_ prefix to the header you want to send. For example if you want to pass header X-HTTP-Method-Override you specify it like so:

    $client->request(
        Request::METHOD_POST,
        '/api/v1/something',
        $body,
        [],
        ['HTTP_X-HTTP-Method-Override' => Request::METHOD_GET]
    );
Mariko answered 31/1, 2018 at 12:46 Comment(0)
S
0

In addition to the HTTP_ suffix you have to be careful how you try to access them, more information below.

For that request :
     $this->client->request(
            Request::METHOD_POST,
            '/api/auth/login',
            [],
            [],
            [
                'CONTENT_TYPE' => 'application/json',
                'HTTP_X-interface' => "string",
            ],
            json_encode([
                'username' => "[email protected]",
                'password' => "exemplePassword"
            ]));
I want get header with : $request->headers->get('X-interface');

I have an event listener that listens for the 'authentication_success' event for the Lexik JWT bundle.

public function onAuthenticationSuccess(AuthenticationSuccessEvent $event)
{
    $request    = Request::createFromGlobals();
    $interface  = $request->headers->get('X-interface'); // null
}

To

public function onAuthenticationSuccess(AuthenticationSuccessEvent $event)
{
    $requestStack = $this->container->get('request_stack');
    $request = $requestStack->getMainRequest();
  $interface = $request->headers->get('X-interface'); // i have header
}

The Request::createFromGlobals() method works in production because the current request headers are available in the global variables. These global variables are defined by the web server before the request is received by PHP.

In a functional test, the current request headers are not available in the global variables. Therefore, the Request::createFromGlobals() method returns a new request that does not contain the current request headers.

A last exemple :

 #[Route('/postTest', name: 'postTest', methods: ['post'])]

    public function postTest(Request $request)
    {
        dd($_SERVER);
    }

With postMan : i have the header in the super global $_SERVER

With $client->request in the test (KernelBrowser) : I don't have header in the super global $_SERVER

Scapula answered 13/9, 2023 at 14:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.