Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[HttpKernel] Adding new#[MapRequestHeader] attribute and resolver#51379

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
StevenRenaux wants to merge1 commit intosymfony:7.4
base:7.4
Choose a base branch
Loading
fromStevenRenaux:map-request-header-attribute

Conversation

StevenRenaux
Copy link
Contributor

@StevenRenauxStevenRenaux commentedAug 14, 2023
edited
Loading

QA
Branch?6.4
Bug fix?no
New feature?yes
Deprecations?no
Tickets#51342
LicenseMIT
Doc PR#20541

Hi,

Related to this#51342 I tried to work on this PR.
To use this new attribute, you just need to add it in your method of your controller.

namespaceApp\Controller;class TestingControllerextends AbstractController{    #[Route('/', name:'home', methods:'GET')]publicfunctionhome(        #[MapRequestHeader]array$accept,        #[MapRequestHeader('accept')]string$foo,        #[MapRequestHeader('user-agent')] ?string$bar,        #[MapRequestHeader(name:'accept-encoding')]AcceptHeader$encoding,    )    {dump($accept);//        array:7 [▼//          0 => "text/html"//          1 => "application/xhtml+xml"//          2 => "image/avif"//          3 => "image/webp"//          4 => "image/apng"//          5 => "application/xml"//          6 => "*/*"//        ]dump($foo);//  "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8"dump($bar);//  "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"dump($encoding);//        Symfony\Component\HttpFoundation\AcceptHeader {#4727 ▼//            -items: array:4 [▼//                "gzip" =>//                    Symfony\Component\HttpFoundation\AcceptHeaderItem {#2437 ▼//                        -value: "gzip"//                        -quality: 1.0//                        -index: 0//                        -attributes: []//                }//                "deflate" =>//                    Symfony\Component\HttpFoundation\AcceptHeaderItem {#4882 ▼//                        -value: "deflate"//                        -quality: 1.0//                        -index: 1//                        -attributes: []//                }//                "br" =>//                    Symfony\Component\HttpFoundation\AcceptHeaderItem {#4549 ▼//                        -value: "br"//                        -quality: 1.0//                        -index: 2//                        -attributes: []//                }//                "zstd" =>//                    Symfony\Component\HttpFoundation\AcceptHeaderItem {#4773 ▼//                        -value: "zstd"//                        -quality: 1.0//                        -index: 3//                        -attributes: []//                }//            ]//              -sorted: false//        }    }

For some parameters asUser-Agent we need to add the name for the resolver, because the conversion ofuserAgent is not interpreted by the resolver and return an exception as Missing header parameter "userAgent".

And for some others parameters as cookie I don't know what to do, because at the moment it only return string for all of them and is it really useful 🤷

ruudk, qdequippe, helyakin, Koc, maelanleborgne, skigun, nazububu, Zuruuh, and therouv reacted with heart emojikaznovac, helyakin, and ahmedghanem00 reacted with rocket emojihelyakin reacted with eyes emoji
@carsonbot
Copy link

Hey!

I see that this is your first PR. That is great! Welcome!

Symfony has acontribution guide which I suggest you to read.

In short:

  • Always add tests
  • Keep backward compatibility (seehttps://symfony.com/bc).
  • Bug fixes must be submitted against the lowest maintained branch where they apply (seehttps://symfony.com/releases)
  • Features and deprecations must be submitted against the 6.4 branch.

Review the GitHub status checks of your pull request and try to solve the reported issues. If some tests are failing, try to see if they are failing because of this change.

When two Symfony core team members approve this change, it will be merged and you will become an official Symfony contributor!
If this PR is merged in a lower version branch, it will be merged up to all maintained branches within a few days.

I am going to sit back now and wait for the reviews.

Cheers!

Carsonbot

@StevenRenauxStevenRenauxforce-pushed themap-request-header-attribute branch from527c461 toe85136dCompareAugust 14, 2023 11:06
@AurelienPillevesse
Copy link
Contributor

AurelienPillevesse commentedAug 14, 2023
edited
Loading

Maybe I'm wrong but seems that something related tomapQueryString andmapRequestPayload is in this file and I see nothing from yours :

publicfunctiononKernelControllerArguments(ControllerArgumentsEvent$event):void

Why did not add in the same file?

Copy link

@robert-sykesrobert-sykes left a comment
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Would this not be best to also allow it to map to an object, like how theMapRequestPayload currently works, as I can pass anObject as a reference the serializer will deserialize to this object? That way you can have aHeader class that the headers deserialize into.

You can merge it with your current concept and have a bit of best of both? Map individual Headers to an string, or an object or even just an array if required?

Something potentially like this?

privatefunctionmapRequestHeader(Request$request,string$type,MapRequestHeader$attribute): ?object    {$headers = [];$requestHeaders =$request->headers->all();array_walk($requestHeaders,function ($value,$key)use (&$headers) {$key =$this->snakeCaseToCamelCase($key);$headers[$key] =$value[0];        });$headers =json_encode($headers);$format ='json';try {return$this->serializer->deserialize($headers,$type,$format, []);        }catch (UnsupportedFormatException$e) {thrownewHttpException(Response::HTTP_UNSUPPORTED_MEDIA_TYPE,sprintf('Unsupported format: "%s".',$format),$e);        }catch (NotEncodableValueException$e) {thrownewHttpException(Response::HTTP_BAD_REQUEST,sprintf('Request payload contains invalid "%s" data.',$format),$e);        }    }

and you could have a class like this:

class HeaderRequest{publicfunction__construct(publicreadonlystring$userAgent,publicreadonlystring$accept,publicreadonlystring$contentType,publicreadonlystring$acceptEncoding,    ) {    }}

An advantage is you can use the Validator too and enforce any header types if needed or create a HeaderRequest class per request as needed.

You can add this as a new method to the existingRequestPayloadValueResolver as already mentioned by@AurelienPillevesse so it will tie nicely into the existing process.

This is a rough example but just food for thought.

Very useful PR this and something we need, so looking forward to seeing how it progresses :)

@StevenRenauxStevenRenauxforce-pushed themap-request-header-attribute branch from261f6e6 to72cb1eeCompareAugust 17, 2023 14:32
@StevenRenauxStevenRenauxforce-pushed themap-request-header-attribute branch 2 times, most recently fromafbdd35 to90f1015CompareAugust 17, 2023 14:50
@ruudk
Copy link
Contributor

ruudk commentedAug 21, 2023
edited
Loading

Too bad the PR was changed after@robert-sykes suggestion. I think these are 2 distinct ideas. The original PR description mentions a single attribute per header, same as how MapQueryParameter works. There are valid cases for that, where you only want and need a single header scalar.

The updated code now requires you to map a header to a header object.

Would be great to also keep supporting the original one for just a single header.

See this comment where a similar situation happened:#49134 (comment)

robert-sykes and WebMamba reacted with thumbs up emoji

@robert-sykes
Copy link

robert-sykes commentedAug 21, 2023
edited
Loading

Too bad the PR was changed after@robert-sykes suggestion. I think these are 2 distinct ideas. The original PR description mentions a single attribute per header, same as how MapQueryParameter works. There are valid cases for that, where you only want and need a single header scalar.

The updated code now requires you to map a header to a header object.

Would be great to also keep supporting the original one for just a single header.

See this comment where a similar situation happened:#49134 (comment)

I'm all for this, to be fair. I did imply this in my original comment where I saidYou can merge it with your current concept and have a bit of best of both? Map individual Headers to an string, or an object or even just an array if required? That said - I didn't push it any further in my commentary, apologies.

@StevenRenaux You could check the type and if it's a string map to that similar to your original commit, otherwise if it's object map to those fields instead. We get best of both worlds this way. What do you think?

ruudk and StevenRenaux reacted with thumbs up emojiruudk reacted with laugh emoji

@StevenRenaux
Copy link
ContributorAuthor

StevenRenaux commentedAug 21, 2023
edited
Loading

Hey, I will try to do it and I didn't understand well for sure but we are there to share and go further 😉

robert-sykes and chalasr reacted with thumbs up emoji

@robert-sykes
Copy link

Hey, I will try to do it and I didn't understand well for sure but we are there to share and go further 😉

No problem at all. If you need a hand let me know, more than happy to pair on this with you. :)

@StevenRenauxStevenRenauxforce-pushed themap-request-header-attribute branch fromff6b41f to0bda0bfCompareAugust 22, 2023 15:02
@StevenRenaux
Copy link
ContributorAuthor

StevenRenaux commentedAug 22, 2023
edited by OskarStark
Loading

To get back to the original Issue I suggest this

namespaceApp\Controller;class TestControllerextends AbstractController{    #[Route(path:'/', name:'test')]publicfunctiontest(        #[MapRequestHeader]HeaderRequestDto$headerRequestDto,        #[MapRequestHeader(name:'user-agent')]string$agent,        #[MapRequestHeader]array$accept    ):Response    {dd($headerRequestDto,//      App\Entity\HeaderRequestDto {//        accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8"//        agent: "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/116.0"//        acceptEncoding: "gzip, deflate, br"//        host: "localhost:8000"//      }$agent,//      "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/116.0"$accept//      array:6 [//          0 => "text/html"//          1 => "application/xhtml+xml"//          2 => "application/xml;q=0.9"//          3 => "image/avif"//          4 => "image/webp"//          5 => "*/*;q=0.8"//      ]        );    }}

And a Dto could look like this :

namespaceApp\Entity;useSymfony\Component\Serializer\Annotation\SerializedName;useSymfony\Component\Validator\ConstraintsasAssert;class HeaderRequestDto{publicfunction__construct(publicreadonlystring$accept,        #[Assert\EqualTo('test', groups: ['test'])]        #[SerializedName('user-agent')]publicreadonlystring$agent ='agent',        #[SerializedName('accept-encoding')]publicreadonlystring$acceptEncoding,        #[Assert\EqualTo('localhost', groups: ['valid'])]publicreadonlystring$host    ) {    }}

We only use kebab-case (as returned by HeaderBag) now to get some property like 'user-agent'.
And if we want an array rather than a string for the property asaccept it will return an array after an explode with a coma delimiter.

@StevenRenauxStevenRenauxforce-pushed themap-request-header-attribute branch from0bda0bf tocced8c1CompareAugust 22, 2023 15:30
@carsonbotcarsonbot changed the titleAdding a new Attribute MapRequestHeader class and resolver[HttpKernel] Adding a new Attribute MapRequestHeader class and resolverAug 23, 2023
@xabbuhxabbuh added this to the7.2 milestoneMay 15, 2024
@alexandre-daubois
Copy link
Member

Hi@StevenRenaux! What's the current state of this PR? 🙂

@StevenRenaux
Copy link
ContributorAuthor

Hi@StevenRenaux! What's the current state of this PR? 🙂

@alexandre-daubois Waiting for review, since the last requested update.

alexandre-daubois reacted with thumbs up emoji

@fabpotfabpot modified the milestones:7.2,7.3Nov 20, 2024
@StevenRenauxStevenRenaux changed the title[HttpKernel] Adding new#[MapRequestHeader] and#[MapRequestHeaders] attributes and resolver[HttpKernel] Adding new#[MapRequestHeader] attribute and resolverJan 7, 2025
@StevenRenauxStevenRenauxforce-pushed themap-request-header-attribute branch 3 times, most recently from7494a85 to0f38cdeCompareJanuary 7, 2025 13:11
@StevenRenaux
Copy link
ContributorAuthor

StevenRenaux commentedJan 7, 2025
edited
Loading

Back to the basics of PR, using only the MapRequestHeader attribute. Mapping to a DTO does not seem like a relevant or common use case or if it is really necessary could be done in a future PR.

The allowed types are therefore:

  • string
  • array
  • AcceptHeader

When the header parameter cannot be determined by the variable name, we can specify the name argument in the attribute.

publicfunctiontest(    #[MapRequestHeader('user-agent')] ?string$bar,):Response{dump($bar);//  "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"}

If we are looking for a header of type Accept-* with an array type, we will use the dedicated methods to retrieve this data.

https://symfony.com/doc/current/components/http_foundation.html#accessing-accept-headers-data

publicfunctiontest(    #[MapRequestHeader]array$accept,):Response{dump($accept);//        array:7 [▼//          0 => "text/html"//          1 => "application/xhtml+xml"//          2 => "image/avif"//          3 => "image/webp"//          4 => "image/apng"//          5 => "application/xml"//          6 => "*/*"//        ]}

And with AcceptHeader type

publicfunctiontest(    #[MapRequestHeader(name:'accept-encoding')]AcceptHeader$encoding,):Response{dump($encoding);//        Symfony\Component\HttpFoundation\AcceptHeader {#4727 ▼//            -items: array:4 [▼//                "gzip" =>//                    Symfony\Component\HttpFoundation\AcceptHeaderItem {#2437 ▼//                        -value: "gzip"//                        -quality: 1.0//                        -index: 0//                        -attributes: []//                }//                "deflate" =>//                    Symfony\Component\HttpFoundation\AcceptHeaderItem {#4882 ▼//                        -value: "deflate"//                        -quality: 1.0//                        -index: 1//                        -attributes: []//                }//                "br" =>//                    Symfony\Component\HttpFoundation\AcceptHeaderItem {#4549 ▼//                        -value: "br"//                        -quality: 1.0//                        -index: 2//                        -attributes: []//                }//                "zstd" =>//                    Symfony\Component\HttpFoundation\AcceptHeaderItem {#4773 ▼//                        -value: "zstd"//                        -quality: 1.0//                        -index: 3//                        -attributes: []//                }//            ]//              -sorted: false//        }}
Neirda24 reacted with rocket emoji

@StevenRenauxStevenRenauxforce-pushed themap-request-header-attribute branch 2 times, most recently fromfbde828 to89f420fCompareJanuary 10, 2025 08:26
@MatTheCat
Copy link
Contributor

It bugs me thearray type has two semantics whether it applies to anAccept-* header or not. Plus

  • in the first case there already is theAcceptHeader type.
  • in the second case only the first value is returned in an array, but
    • there can be many
    • the first value can actually be many values combined by the SAPI
mathroc reacted with thumbs up emoji

@ruudk
Copy link
Contributor

@StevenRenaux What's needed to get this to a mergeable state? I would love this to be included in the new Symfony version.

@StevenRenaux
Copy link
ContributorAuthor

@StevenRenaux What's needed to get this to a mergeable state? I would love this to be included in the new Symfony version.

@ruudk Waiting reviews from core-contributors, but it's seems to late for merging into the next 7.3 version.
Feel free also to review, approve...
I think at the moment it's fine to get a simple implementation as it is because it's the kind of stuff you can't statifies every problematics.

@ruudk
Copy link
Contributor

Could you rebase it, so that the tests go green?

@StevenRenauxStevenRenauxforce-pushed themap-request-header-attribute branch from89f420f to2142045CompareMay 26, 2025 11:44
@ruudk
Copy link
Contributor

@StevenRenauxStevenRenauxforce-pushed themap-request-header-attribute branch from2142045 to7a123eaCompareMay 26, 2025 15:12
@fabpotfabpot modified the milestones:7.3,7.4May 26, 2025
'accept-charset' => $request->getCharsets(),
'accept-language' => $request->getLanguages(),
'accept-encoding' => $request->getEncodings(),
default => [$request->headers->get($name)],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Suggested change
default =>[$request->headers->get($name)],
default =>$request->headers->all($name),

}

if (null === $value && !$argument->isNullable()) {
throw new HttpException($attribute->validationFailedStatusCode, \sprintf('Missing header "%s".', $name));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I think if type is array we could return an empty array

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@mathrocmathrocmathroc left review comments

@alexandre-dauboisalexandre-dauboisalexandre-daubois left review comments

@robert-sykesrobert-sykesrobert-sykes approved these changes

@WebMambaWebMambaAwaiting requested review from WebMamba

@ycerutoycerutoAwaiting requested review from yceruto

@kbondkbondAwaiting requested review from kbond

@chalasrchalasrAwaiting requested review from chalasr

@dunglasdunglasAwaiting requested review from dunglas

@OskarStarkOskarStarkAwaiting requested review from OskarStark

@jderussejderusseAwaiting requested review from jderusse

@xabbuhxabbuhAwaiting requested review from xabbuh

@nicolas-grekasnicolas-grekasAwaiting requested review from nicolas-grekas

Assignees
No one assigned
Projects
None yet
Milestone
7.4
Development

Successfully merging this pull request may close these issues.

13 participants
@StevenRenaux@carsonbot@AurelienPillevesse@ruudk@robert-sykes@mathroc@mindaugasvcs@alexandre-daubois@MatTheCat@nicolas-grekas@WebMamba@fabpot@xabbuh

[8]ページ先頭

©2009-2025 Movatter.jp