Repository: Flexget/Flexget

Issue:
Trailing slashes in API
### Expected behaviour:
API urls should work with both trailing and none trailing slashes (for example `/api/auth/login` and `/api/auth/login/`)

### Actual behaviour:
Only the ones with trailing slashes work, the other ones throw 500 errors (debug logs consumed by cherrypy)
### Steps to reproduce:
- Step 1: Setup web server
- Step 2: Call endpoint without trailing slash

#### Config:
```
web_server: yes
```
  
#### Log:
```
2017-01-16 15:55 ERROR    cherrypy.error                 [16/Jan/2017:15:55:04] ENGINE FormDataRoutingRedirect('A request was sent to this URL (http://localhost:5050/api/auth/login) but a redirect was issued automatically by the routing system to "http://localhost:5050/api/auth/login/".  The URL was defined with a trailing slash so Flask will automatically redirect to the URL with the trailing slash if it was accessed without one.  Make sure to directly send your POST-request to this URL since we can\'t make browsers or HTTP clients redirect with form data reliably or without user interaction.\n\nNote: this exception is only raised in debug mode',)
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/cherrypy/wsgiserver/__init__.py", line 1408, in communicate
    req.respond()
  File "/usr/local/lib/python2.7/dist-packages/cherrypy/wsgiserver/__init__.py", line 862, in respond
    self.server.gateway(self).respond()
  File "/usr/local/lib/python2.7/dist-packages/cherrypy/wsgiserver/__init__.py", line 2335, in respond
    response = self.req.server.wsgi_app(self.env, self.start_response)
  File "/usr/local/lib/python2.7/dist-packages/cherrypy/_cptree.py", line 287, in __call__
    return app(environ, start_response)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1994, in __call__
    return self.wsgi_app(environ, start_response)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1985, in wsgi_app
    response = self.handle_exception(e)
  File "/usr/local/lib/python2.7/dist-packages/flask_restful/__init__.py", line 271, in error_router
    return original_handler(e)
  File "/usr/local/lib/python2.7/dist-packages/flask_cors/extension.py", line 161, in wrapped_function
    return cors_after_request(app.make_response(f(*args, **kwargs)))
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1540, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python2.7/dist-packages/flask_restful/__init__.py", line 271, in error_router
    return original_handler(e)
  File "/usr/local/lib/python2.7/dist-packages/flask_cors/extension.py", line 161, in wrapped_function
    return cors_after_request(app.make_response(f(*args, **kwargs)))
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1590, in dispatch_request
    self.raise_routing_exception(req)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1576, in raise_routing_exception
    raise FormDataRoutingRedirect(request)
FormDataRoutingRedirect: A request was sent to this URL (http://localhost:5050/api/auth/login) but a redirect was issued automatically by the routing system to "http://localhost:5050/api/auth/login/".  The URL was defined with a trailing slash so Flask will automatically redirect to the URL with the trailing slash if it was accessed without one.  Make sure to directly send your POST-request to this URL since we can't make browsers or HTTP clients redirect with form data reliably or without user interaction.

Note: this exception is only raised in debug mode
```

### Additional information:

- Flexget Version: latest dev (2.9.6.dev)
- Python Version: 2.7.6
- Installation method: Github
- OS and version: Ubuntu 14.04

Cherrypy has a tool to solve this, but because we graft the WSGI Flask applications, it's not usable. This should probably be resolved from inside the Flask api app itself.

Trailing slashes in API
### Expected behaviour:
API urls should work with both trailing and none trailing slashes (for example `/api/auth/login` and `/api/auth/login/`)

### Actual behaviour:
Only the ones with trailing slashes work, the other ones throw 500 errors (debug logs consumed by cherrypy)
### Steps to reproduce:
- Step 1: Setup web server
- Step 2: Call endpoint without trailing slash

#### Config:
```
web_server: yes
```
  
#### Log:
```
2017-01-16 15:55 ERROR    cherrypy.error                 [16/Jan/2017:15:55:04] ENGINE FormDataRoutingRedirect('A request was sent to this URL (http://localhost:5050/api/auth/login) but a redirect was issued automatically by the routing system to "http://localhost:5050/api/auth/login/".  The URL was defined with a trailing slash so Flask will automatically redirect to the URL with the trailing slash if it was accessed without one.  Make sure to directly send your POST-request to this URL since we can\'t make browsers or HTTP clients redirect with form data reliably or without user interaction.\n\nNote: this exception is only raised in debug mode',)
Traceback (most recent call last):
  File "/usr/local/lib/python2.7/dist-packages/cherrypy/wsgiserver/__init__.py", line 1408, in communicate
    req.respond()
  File "/usr/local/lib/python2.7/dist-packages/cherrypy/wsgiserver/__init__.py", line 862, in respond
    self.server.gateway(self).respond()
  File "/usr/local/lib/python2.7/dist-packages/cherrypy/wsgiserver/__init__.py", line 2335, in respond
    response = self.req.server.wsgi_app(self.env, self.start_response)
  File "/usr/local/lib/python2.7/dist-packages/cherrypy/_cptree.py", line 287, in __call__
    return app(environ, start_response)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1994, in __call__
    return self.wsgi_app(environ, start_response)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1985, in wsgi_app
    response = self.handle_exception(e)
  File "/usr/local/lib/python2.7/dist-packages/flask_restful/__init__.py", line 271, in error_router
    return original_handler(e)
  File "/usr/local/lib/python2.7/dist-packages/flask_cors/extension.py", line 161, in wrapped_function
    return cors_after_request(app.make_response(f(*args, **kwargs)))
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1540, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python2.7/dist-packages/flask_restful/__init__.py", line 271, in error_router
    return original_handler(e)
  File "/usr/local/lib/python2.7/dist-packages/flask_cors/extension.py", line 161, in wrapped_function
    return cors_after_request(app.make_response(f(*args, **kwargs)))
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1590, in dispatch_request
    self.raise_routing_exception(req)
  File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1576, in raise_routing_exception
    raise FormDataRoutingRedirect(request)
FormDataRoutingRedirect: A request was sent to this URL (http://localhost:5050/api/auth/login) but a redirect was issued automatically by the routing system to "http://localhost:5050/api/auth/login/".  The URL was defined with a trailing slash so Flask will automatically redirect to the URL with the trailing slash if it was accessed without one.  Make sure to directly send your POST-request to this URL since we can't make browsers or HTTP clients redirect with form data reliably or without user interaction.

Note: this exception is only raised in debug mode
```

### Additional information:

- Flexget Version: latest dev (2.9.6.dev)
- Python Version: 2.7.6
- Installation method: Github
- OS and version: Ubuntu 14.04

Cherrypy has a tool to solve this, but because we graft the WSGI Flask applications, it's not usable. This should probably be resolved from inside the Flask api app itself.



Discussion:

Resolving patch:
diff --git a/flexget/api/app.py b/flexget/api/app.py
--- a/flexget/api/app.py
+++ b/flexget/api/app.py
@@ -231,6 +231,7 @@ def pagination_parser(self, parser=None, sort_choices=None, default=None, add_so
 api_app.config['REMEMBER_COOKIE_NAME'] = 'flexget.token'
 api_app.config['DEBUG'] = True
 api_app.config['ERROR_404_HELP'] = False
+api_app.url_map.strict_slashes = False
 
 CORS(api_app)
 Compress(api_app)


Test patch: