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

bpo-46436: Fix command-line option -d/--directory in module http.server #30701

Merged
merged 1 commit into from Feb 3, 2022

Conversation

maggyero
Copy link
Contributor

@maggyero maggyero commented Jan 19, 2022

Fix command-line option -d/--directory in http.server main
function that was ignored when combined with --cgi.

https://bugs.python.org/issue46436

Automerge-Triggered-By: GH:merwok

Automerge-Triggered-By: GH:merwok

@maggyero maggyero changed the title Add alternative directory support (-d/--directory option) to http.server CLI for CGIHTTPRequestHandler Pass -d/--directory command-line option to http.server.CGIHTTPRequestHandler Jan 19, 2022
@maggyero maggyero changed the title Pass -d/--directory command-line option to http.server.CGIHTTPRequestHandler Pass the -d/--directory command-line option to http.server.CGIHTTPRequestHandler Jan 19, 2022
@maggyero maggyero changed the title Pass the -d/--directory command-line option to http.server.CGIHTTPRequestHandler bpo-46436: Pass the -d/--directory command-line option to http.server.CGIHTTPRequestHandler Jan 19, 2022
Lib/http/server.py Outdated Show resolved Hide resolved
Lib/http/server.py Outdated Show resolved Hide resolved
Copy link
Member

@JelleZijlstra JelleZijlstra left a comment

The substantive change looks good and I confirmed that it worked, but I agree that you should back out the unnecessary changes such as those in import order. They're not necessary to the fix.

@maggyero maggyero requested review from JelleZijlstra and merwok Jan 22, 2022
Copy link
Member

@merwok merwok left a comment

Thanks! Do revert the import change then this can be merged

@bedevere-bot
Copy link

bedevere-bot commented Jan 22, 2022

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

@maggyero
Copy link
Contributor Author

maggyero commented Jan 22, 2022

@merwok Done.

I have made the requested changes; please review again.

@bedevere-bot
Copy link

bedevere-bot commented Jan 22, 2022

Thanks for making the requested changes!

@merwok: please review the changes made to this pull request.

@bedevere-bot bedevere-bot requested a review from merwok Jan 22, 2022
@merwok
Copy link
Member

merwok commented Jan 23, 2022

Please see https://bugs.python.org/issue46285

@maggyero
Copy link
Contributor Author

maggyero commented Jan 23, 2022

Thanks for mentioning this issue @merwok.

As you pointed out, function test in module http.server expects a real request handler class argument (SimpleHTTPRequestHandler or CGIHTTPRequestHandler), not a partial object partial(SimpleHTTPRequestHandler, directory=args.directory) or partial(CGIHTTPRequestHandler, directory=args.directory), so that the assignment of class attribute protocol_version in test is not ignored.

The partial object in the if __name__ == '__main__': branch of module http.server was introduced in the first place to pass the directory argument at request handler class instantiation in method BaseServer.finish_request of module socketserver:

def finish_request(self, request, client_address):
    """Finish one request by instantiating RequestHandlerClass."""
    self.RequestHandlerClass(request, client_address, self)

But method BaseServer.finish_request is a factory method of class BaseServer (the abstract creator) so it is designed to be overridden in subclasses to customize the instantiation of request handler subclasses of class BaseRequestHandler (the abstract product). So the proper way to instantiate subclasses SimpleHTTPRequestHandler and CGIHTTPRequestHandler with the directory argument is to override BaseServer.finish_request, not using a partial object.

I have just updated my PR to implement this. It fixes both #46285 and #46436. It also adds a command-line option -p/--protocol to module http.server and passes it to function test in the if __name__ == '__main__' branch (the protocol argument of test is now no longer ignored since we also pass a real request handler class instead of a partial object).

@maggyero maggyero changed the title bpo-46436: Pass the -d/--directory command-line option to http.server.CGIHTTPRequestHandler bpo-46436: Pass command-line option -d/--directory to CGIHTTPRequestHandler and add command-line option -p/--protocol in module http.server Jan 23, 2022
@maggyero maggyero changed the title bpo-46436: Pass command-line option -d/--directory to CGIHTTPRequestHandler and add command-line option -p/--protocol in module http.server bpo-46436: No longer ignore command-line option -d/--directory in module http.server when --cgi is used, and add -p/--protocol Jan 23, 2022
@merwok
Copy link
Member

merwok commented Jan 23, 2022

Thanks for fixing both issues! I’ll review the code to see if it also addresses my bad feeling about setting attributes directly on class objects.

Can we reference two tickets in one pull request title? Also have two blurb notes?

Lib/http/server.py Outdated Show resolved Hide resolved
Lib/http/server.py Show resolved Hide resolved
@merwok
Copy link
Member

merwok commented Jan 23, 2022

Nice trick with using a closure to keep finish_request’s signature compliant with the definition in socketserver.
On the other hand, I wonder if it wouldn’t be more straightforward to add a directory parameter to test.

test still sets attributes on the passed classes directly, which I find fishy, but it’s not the job of this PR to change that, and maybe it doesn’t need to be fixed at all (it’s a main function, not one that would be imported and called from regular code).

@maggyero
Copy link
Contributor Author

maggyero commented Jan 24, 2022

Nice trick with using a closure to keep finish_request’s signature compliant with the definition in socketserver. On the other hand, I wonder if it wouldn’t be more straightforward to add a directory parameter to test.

Yes that is another solution: moving the creation of partial objects with argument directory after the assignment of class attribute protocol_version in function test. The drawback of this approach is that, as you mentioned, it requires changing the signature of test (though it would be backward compatible and test is not part of the API of module http.server), and it requires such a change each time the signature of the __init__ method of a handler subclass changes (i.e. it couples test with __init__).

Factory methods (like finish_request) are a design pattern that avoids such information distribution.

@merwok
Copy link
Member

merwok commented Jan 24, 2022

I wasn’t suggesting to use partial objects, if that’s necessary then keeping your technique is better.
(Otherwise I don’t mind changing the signature of test, just like it was changed for protocol)

@maggyero
Copy link
Contributor Author

maggyero commented Jan 25, 2022

I wasn’t suggesting to use partial objects, if that’s necessary then keeping your technique is better.
(Otherwise I don’t mind changing the signature of test, just like it was changed for protocol)

Yes I think that is necessary. To instantiate a request handler with the directory argument from the method finish_request of a server, we have only two solutions:

  1. The partial object solution: pass a callable partial(RequestHandlerClass, directory=directory) to the server as the RequestHandlerClass argument (which becomes the self.RequestHandlerClass instance attribute) and let the server inherit the method finish_request of the class socketserver.BaseServer:
    def finish_request(self, request, client_address):
        """Finish one request by instantiating RequestHandlerClass."""
        self.RequestHandlerClass(request, client_address, self)
  1. The factory method solution: override the method finish_request of the class socketserver.BaseServer with the instantiation of the class RequestHandlerClass:
    def finish_request(self, request, client_address):
        RequestHandlerClass(request, client_address, self, directory=directory)

The designer of the class socketserver.BaseServer gave us the two possibilities. In the first solution, finish_request is a useless factory method. In the second solution, self.RequestHandlerClass is a useless instance attribute.

@orsenthil, do you a preference?

@maggyero maggyero changed the title bpo-46436: Fix ignored command-line option -d/--directory in module http.server when --cgi is used bpo-46436: Fix command-line option -d/--directory in module http.server Jan 30, 2022
@maggyero
Copy link
Contributor Author

maggyero commented Jan 31, 2022

Thanks for getting the PR ready to merge!
Can you confirm that you tested it locally?

Thanks for reviewing it @merwok! I cleaned up my history and tested the HTTP server locally with Curl for both PRs and I confirm that they both work. You can merge them.

@merwok
Copy link
Member

merwok commented Jan 31, 2022

Can you add your name to Misc/ACKS?

@maggyero
Copy link
Contributor Author

maggyero commented Jan 31, 2022

Can you add your name to Misc/ACKS?

@merwok It is already there actually.

@merwok merwok added the 🤖 automerge PR will be merged once it's been approved and all CI passed label Jan 31, 2022
@miss-islington
Copy link
Contributor

miss-islington commented Jan 31, 2022

Sorry, I can't merge this PR. Reason: You're not authorized to push to this branch. Visit https://docs.github.com/articles/about-protected-branches/ for more information..

@merwok merwok self-assigned this Jan 31, 2022
@maggyero
Copy link
Contributor Author

maggyero commented Feb 3, 2022

@merwok Is there anything that I can do to let miss-islington merge?

@merwok merwok added 🤖 automerge PR will be merged once it's been approved and all CI passed and removed 🤖 automerge PR will be merged once it's been approved and all CI passed labels Feb 3, 2022
@miss-islington miss-islington merged commit 2d08034 into python:main Feb 3, 2022
12 checks passed
@miss-islington
Copy link
Contributor

miss-islington commented Feb 3, 2022

Thanks @maggyero for the PR 🌮🎉.. I'm working now to backport this PR to: 3.9, 3.10.
🐍🍒🤖

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Feb 3, 2022
…er (pythonGH-30701)

Fix command-line option -d/--directory in http.server main
function that was ignored when combined with --cgi.

Automerge-Triggered-By: GH:merwok
(cherry picked from commit 2d08034)

Co-authored-by: Géry Ogam <gery.ogam@gmail.com>
@bedevere-bot
Copy link

bedevere-bot commented Feb 3, 2022

GH-31102 is a backport of this pull request to the 3.10 branch.

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Feb 3, 2022
…er (pythonGH-30701)

Fix command-line option -d/--directory in http.server main
function that was ignored when combined with --cgi.

Automerge-Triggered-By: GH:merwok
(cherry picked from commit 2d08034)

Co-authored-by: Géry Ogam <gery.ogam@gmail.com>
@bedevere-bot
Copy link

bedevere-bot commented Feb 3, 2022

GH-31103 is a backport of this pull request to the 3.9 branch.

@merwok
Copy link
Member

merwok commented Feb 3, 2022

The main branch was locked temporarily, tests were always failing because of a missing indent in a new test.

@maggyero
Copy link
Contributor Author

maggyero commented Feb 3, 2022

@merwok Thanks a lot for your careful review! It really improved the quality of this PR.

I think we can now merge the other PR.

@maggyero maggyero deleted the patch-20 branch Feb 8, 2022
Mariatta pushed a commit that referenced this pull request Feb 14, 2022
…er (GH-30701)

Fix command-line option -d/--directory in http.server main
function that was ignored when combined with --cgi.

Automerge-Triggered-By: GH:merwok
(cherry picked from commit 2d08034)

Co-authored-by: Géry Ogam <gery.ogam@gmail.com>

Co-authored-by: Géry Ogam <gery.ogam@gmail.com>
Mariatta pushed a commit that referenced this pull request Feb 14, 2022
…er (GH-30701)

Fix command-line option -d/--directory in http.server main
function that was ignored when combined with --cgi.

Automerge-Triggered-By: GH:merwok
(cherry picked from commit 2d08034)

Co-authored-by: Géry Ogam <gery.ogam@gmail.com>

Co-authored-by: Géry Ogam <gery.ogam@gmail.com>
hello-adam pushed a commit to hello-adam/cpython that referenced this pull request Jun 2, 2022
…er (pythonGH-30701)

Fix command-line option -d/--directory in http.server main
function that was ignored when combined with --cgi.

Automerge-Triggered-By: GH:merwok
(cherry picked from commit 2d08034)

Co-authored-by: Géry Ogam <gery.ogam@gmail.com>

Co-authored-by: Géry Ogam <gery.ogam@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🤖 automerge PR will be merged once it's been approved and all CI passed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants