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

feat: add IncomingRequest::is() method #6995

Merged
merged 10 commits into from
Dec 24, 2022
Merged

Conversation

kenjis
Copy link
Member

@kenjis kenjis commented Dec 20, 2022

Description
Writing code like strtolower($this->request->getMethod()) !== 'post' is a pain.

  • add IncomingRequest::is()
$request->is('get')
$request->is('post')
$request->is('put')
$request->is('delete')
$request->is('head')
$request->is('patch')
$request->is('options')
$request->is('json')
$request->is('ajax')

Checklist:

  • Securely signed commits
  • Component(s) with PHPDoc blocks, only if necessary or adds value
  • Unit testing, with >80% coverage
  • User guide updated
  • Conforms to style guide

@kenjis kenjis added enhancement PRs that improve existing functionalities 4.3 labels Dec 20, 2022
Copy link
Contributor

@datamweb datamweb left a comment

Choose a reason for hiding this comment

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

To be beautiful code.😄

return strtolower($this->getMethod()) === $value;
}

if ($value === 'json') {
Copy link
Member

Choose a reason for hiding this comment

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

Not sure if json belong here. But if we will have it, why not also have ajax? Basically the same story.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm fine to add ajax.

Copy link
Member Author

Choose a reason for hiding this comment

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

Added.

Copy link
Collaborator

Choose a reason for hiding this comment

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

We already have the isAJAX() method.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, we have, and as you may notice, we use it. IMO proposed is() method would serve as a convenient shortcut, so I don't see a problem with another way of accessing the same method.

@iRedds
Copy link
Collaborator

iRedds commented Dec 20, 2022

public function isMethod(string $method) : bool {}
public function isGet() : bool {}
public function isPost() : bool {}
// e.t.c.
  1. the default method name is in uppercase.
    The fact that in the framework the method name is in lowercase is the wrong way.

@kenjis
Copy link
Member Author

kenjis commented Dec 20, 2022

The fact that in the framework the method name is in lowercase is the wrong way.

What do you mean? Why is lowercase wrong way?

@iRedds
Copy link
Collaborator

iRedds commented Dec 20, 2022

The fact that in the framework the method name is in lowercase is the wrong way.

What do you mean? Why is lowercase wrong way?

Because "the default method name is in uppercase."
Converting to lowercase is an overhead.

@MGatner
Copy link
Member

MGatner commented Dec 20, 2022

I think @iRedds was pointing out that we only need this method because we are inconsistent with our case in the getMethod() return. The $upper parameter is already deprecated which means we are currently forcing lowercase method names. However if we want to go PSR-7 we cannot modify the case:

     * While HTTP method names are typically all uppercase characters, HTTP
     * method names are case-sensitive and thus implementations SHOULD NOT
     * modify the given string.

I'm not sure the best approach here. I am not opposed to this helper method, but I also believe it should be unnecessary.

@michalsn
Copy link
Member

The lowercase/uppercase "problem" was indeed created by PSR-7 compatibility. I don't see a way to resolve it without introducing quite a big BC break because, by default, everything is in lowercase now (and was the same way in CI3).

@kenjis
Copy link
Member Author

kenjis commented Dec 20, 2022

Because "the default method name is in uppercase."

The method token is case-sensitive because it might be used as a gateway to object-based systems with case-sensitive method names. By convention, standardized methods are defined in all-uppercase US-ASCII letters.
https://www.rfc-editor.org/rfc/rfc9110#name-overview

It seems method names should be case-sensitive.

The getMethod() returns lowercase now.
So strtolower($this->getMethod()) === $value; is redundant now.
But the default $upper = false in getMethod() will be removed,
so we should not depend on it.

@kenjis kenjis force-pushed the feat-request-is branch 2 times, most recently from 4f364b4 to 5848832 Compare December 21, 2022 08:22
@kenjis
Copy link
Member Author

kenjis commented Dec 21, 2022

@iRedds Do you say that the standard HTTP method names are in uppercase?
I changed the implementation a bit.

$ curl -X get https://www.w3.org/ -i
HTTP/2 400 
server: cloudflare
date: Wed, 21 Dec 2022 08:40:47 GMT
content-type: text/html
content-length: 155
cf-ray: -

<html>
<head><title>400 Bad Request</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<hr><center>cloudflare</center>
</body>
</html>

@MGatner
Copy link
Member

MGatner commented Dec 21, 2022

I think case-sensitivity is in our favor. We don't need to adjust the case on the method return because Get is not GET. Forcing these to lower does appear to be a violation of the spec; maybe we add a new method for now?

@kenjis
Copy link
Member Author

kenjis commented Dec 22, 2022

The lowercase/uppercase "problem" was indeed created by PSR-7 compatibility. I don't see a way to resolve it without introducing quite a big BC break because, by default, everything is in lowercase now (and was the same way in CI3).

Yes, the current getMethod() returns values that are converted to lowercase, and it seems a violation of the HTTP specification.

The behavior should be fixed but it is a big BC break. So it is better that we wait for v5.0.

@MGatner This is() method is the new method to check HTTP methods in case insensitive manner.

@michalsn
Copy link
Member

The behavior should be fixed but it is a big BC break. So it is better that we wait for v5.0.

I agree with this.

is() may serve as a handful helper method, and since it handles json and ajax it's not 100% redundant with getMethod().

@kenjis kenjis added the docs needed Pull requests needing documentation write-ups and/or revisions. label Dec 22, 2022
@kenjis
Copy link
Member Author

kenjis commented Dec 22, 2022

Rebased and resolved, and all green!

@kenjis
Copy link
Member Author

kenjis commented Dec 22, 2022

Added docs.

Copy link
Member

@MGatner MGatner left a comment

Choose a reason for hiding this comment

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

I do t feel great about it but I agree with the logic that landed here. Definitely we should fix all this in v5.

Also, we need to move away from our AJAX methods as they are less and less reliable; maybe in the future we can provide some different terms for the same concept.

@MGatner MGatner added the next major version? Read this for a relevant v5 idea label Dec 22, 2022
@michalsn
Copy link
Member

next major version?

@MGatner I'm not sure if this label was meant to be added to this PR, but if so, I would have second thoughts about this PR. v5 means that we already have the getMethod() fixed, so is() method wouldn't make as much sense to me.

Then, I would rather add the isJSON() method.

@MGatner
Copy link
Member

MGatner commented Dec 22, 2022

@michalsn I've been using that label for PRs or threads I want to come back and review for v5 content. It doesn't necessarily mean "this PR belongs in v5" (though sometimes) but more like "read this thread for a relevant v5 idea".

@kenjis
Copy link
Member Author

kenjis commented Dec 23, 2022

Rebased and pushed two commits.

@kenjis kenjis removed the docs needed Pull requests needing documentation write-ups and/or revisions. label Dec 23, 2022
We need the same method in CLIRequest because Controller can be run via CLI.
@kenjis kenjis merged commit 8f3cf8b into codeigniter4:4.3 Dec 24, 2022
@kenjis kenjis deleted the feat-request-is branch December 24, 2022 23:15
@kenjis
Copy link
Member Author

kenjis commented Dec 25, 2022

Then, I would rather add the isJSON() method.

I found isJSON() method. It was deprecated in 4.0.5.
See https://github.com/codeigniter4/CodeIgniter4/pull/7019/files#diff-2cab244a084ce08ac666dff9a88aee13003b4170f6c02a690263e3260dac26d8R35

And it was removed in 4.1.2.
See 55b43083

Ah, it was added in 4.0.5.
https://github.com/codeigniter4/framework/blob/v4.0.5/system/HTTP/Message.php#L143

@michalsn
Copy link
Member

Well... it's strange to me why we deprecated isJSON()... and now we're, in fact, introducing it again. I tried to follow the related discussions, but I still have no point. Anyway, I don't mind it at all. This is a common functionality that will make the life of developers easier. At least, in my opinion.

@MGatner
Copy link
Member

MGatner commented Dec 26, 2022

I think isJSON() was removed when we were trying to establish PSR-7 compatibility, but before we split framework-specific methods out into traits. At least that's my best recollection. It's convenient, I have no problem with it, but it is one more framework-coupling method that doesn't save on lines of code or much readability.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
4.3 enhancement PRs that improve existing functionalities next major version? Read this for a relevant v5 idea
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants