mvantellingen / localshop

local pypi server (custom packages and auto-mirroring of pypi)
MIT License
396 stars 112 forks source link

Search command returns 401 - UNAUTHORIZED #90

Closed Razer6 closed 9 years ago

Razer6 commented 11 years ago

Summary

Creating a search request to localshop returns 401 - UNAUTHORIZED although normal package installation works.

Steps to reproduce

pip search --index http://HOST:8000/simple/ flask

Expected behavior

It should return the available packages

Observed behavior

Following error message

$ pip search --index http://HOST:8000/simple/ flask
Exception:
Traceback (most recent call last):
  File "c:\temp\.venv\lib\site-packages\pip\basecommand.py", line 134, in main
    status = self.run(options, args)
  File "c:\temp\.venv\lib\site-packages\pip\commands\search.py", line 38, in run
    pypi_hits = self.search(query, index_url)
  File "c:\temp\.venv\lib\site-packages\pip\commands\search.py", line 52, in search
    hits = pypi.search({'name': query, 'summary': query}, 'or')
  File "c:\Python33\Lib\xmlrpc\client.py", line 1090, in __call__
    return self.__send(self.__name, args)
  File "c:\Python33\Lib\xmlrpc\client.py", line 1419, in __request
    verbose=self.__verbose
  File "c:\Python33\Lib\xmlrpc\client.py", line 1132, in request
    return self.single_request(host, handler, request_body, verbose)
  File "c:\Python33\Lib\xmlrpc\client.py", line 1164, in single_request
    dict(resp.getheaders())
xmlrpc.client.ProtocolError: <ProtocolError for HOST:8000/simple/: 401 UNAUTHORIZED>

This issue can be tracked down using directly a RPC-call:

try:
    import xmlrpclib
except:  
    # Python 3
    import xmlrpc.client as xmlrpclib
client = xmlrpclib.ServerProxy("http:// HOST:8000/simple/")
client.search({'name': 'flask'})
Razer6 commented 11 years ago

After debugging a bit found following problem: A RPC to xmlrpclib.ServerProxy("http:// HOST:8000/simple/") will result to a postrequest to this URL. Since localshop only listens on "http:// HOST:8000/RPC2/" for RPCs this request will be routed to the simpleindex where it will fail.

A quick fix would be in https://github.com/mvantellingen/localshop/blob/develop/localshop/apps/packages/views.py#L47


    def post(self, request):
        parse_distutils_request(request)

        if request.META['CONTENT_TYPE'] == 'text/xml':
            # We got XML date, assume it's a RPC
            return xmlrpc.handle_request(request)

The question then is why we need the routing to RPC2

erickwilder commented 9 years ago

I think this is not a bug. The /simple endpoint is used to discover/install packages. Search is made through an XMLRPC API. The official PyPI website itself doesn't do anything with pip search pointing to /simple:


pip search --index https://pypi.python.org/simple flask                                                                                                                                                                                                               
Exception:
Traceback (most recent call last):
  File "/Users/erick.wilder/.virtualenvs/localshop/lib/python2.7/site-packages/pip/basecommand.py", line 246, in main
    status = self.run(options, args)
  File "/Users/erick.wilder/.virtualenvs/localshop/lib/python2.7/site-packages/pip/commands/search.py", line 43, in run
    pypi_hits = self.search(query, options)
  File "/Users/erick.wilder/.virtualenvs/localshop/lib/python2.7/site-packages/pip/commands/search.py", line 60, in search
    hits = pypi.search({'name': query, 'summary': query}, 'or')
  File "/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py", line 1233, in __call__
    return self.__send(self.__name, args)
  File "/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py", line 1591, in __request
    verbose=self.__verbose
  File "/Users/erick.wilder/.virtualenvs/localshop/lib/python2.7/site-packages/pip/download.py", line 788, in request
    return self.parse_response(response.raw)
  File "/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py", line 1482, in parse_response
    return u.close()
  File "/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py", line 792, in close
    raise ResponseError()
ResponseError: ResponseError()

The right endpoint at the official PyPI is /pypi:

pip search --index https://pypi.python.org/pypi flask

Flask-AppBuilder                         - Simple and rapid application development framework, built on top of Flask. includes detailed security, auto CRUD generation for your models, google charts and much more.
haven                                    - flask's style binary server framework
ShelfCMS                                 - Enhancing flask microframework with beautiful admin                 and cms-like features
... long list of packages ...
Flask-MoSession                          - Mongodb based server side session management system for Flask
restpager                                - A RESTful pager class for Flask
Flask-Flipper                            -
Flask-Profile                            - Flask Application Profiler

The /RPC2 endpoint is the same thing. To be honest, I think we should keep the same endpoint /pypi instead of /RPC2 to deal with those XMLRPC requests.