Adding werkzeug custom converters

Still loving nameko! One day I’ll actually finish my project that uses it.

I’d like to add custom werkzeug converter to my http interfaces, but I’m not exactly sure how to register the converter with nameko. Werkzeug docs want me to add the converter to the app’s url_map, but I’m just not sure what the right way to do that is.

After poking around at the nameko handlers, maybe the right thing to do is to reference the WebServer from the HttpRequestHandler class; but I couldn’t see a way to get the url_map to register my custom converter. I saw a way to make a new url_map, but I’m guessing that would not be seen by the main webserver app.

Any ideas?

Thanks again for all that you do for this, Matt.

-Eric

Hi @erichorne,

Glad you’re enjoying Nameko :slight_smile:

Without knowing the Werkzeug docs you’re referring to, I can suggest a clunky way to do this by subclassing both the WebServer and the HttpEntrypoint.

Here’s a real example from a codebase I work on:

(Obviously you will want to customise this for your use case)

# web.py
from nameko.web import server, handlers

class AuthWebServer(server.WebServer):
    """
    WebServer subclass that captures Authorization header.
    """

    def context_data_from_headers(self, request):
        context_data = {}

        jwt = request.headers.get("Authorization")
        if jwt and jwt.startswith("JWT "):
            jwt = jwt[4:]
        context_data["auth"] = jwt

        return context_data

class AuthServerMixin:
    """
    Mixin for HttpRequestHandlers that uses a WebServer which captures a JWT token
    from the Authorization header.
    """
    server = AuthWebServer()


class HttpEntrypoint(AuthServerMixin, handlers.HttpRequestHandler):
    """ Define an HTTP entrypoint with Auth Mixin defined above.
    """

http = HttpEntrypoint.decorator

Now in your service you just need to use the decorator from your subclass instead

from myservice.web import http

class Service:
    @http()
    def ...

One gotcha with this approach is that you have to exclusively use the subclassed entrypoint in your service. If you also try to use the non-subclassed version from nameko.web.handlers you’ll send up with two WebServer instances. They’ll both manage to bind to the same port and you’ll get weird 404 errors as requests round-robin between them. We learned that lesson the hard way :slight_smile: