Skip to content

hasansezertasan/asgi-user-agents

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

32 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

asgi-user-agents

CI Coverage PyPI - Version PyPI - Python Version License Latest Commit

Downloads Downloads/Month Downloads/Week

User Agents integration for ASGI applications. Works with Starlette, FastAPI, Quart, Litestar -- or any other web framework supporting ASGI that exposes the ASGI scope.


Table of Contents

Installation

NOTE: This is alpha software. Please be sure to pin your dependencies.

Latest Release

pip install asgi-user-agents

Development Version

pip install git+https://github.com/hasansezertasan/asgi-user-agents.git

How does it work?

It simply adds a ua attribute to the request scope. This attribute is an instance of the UADetails class which abstracts the UserAgent class from the user-agents package ๐Ÿ“„.

Usage

It's pretty simple. Just add the middleware to your ASGI application and access the ua attribute from the request scope.

from asgi_user_agents import UAMiddleware
from asgi_user_agents import UARequest as Request
from fastapi.applications import FastAPI
from starlette.middleware import Middleware
from starlette.responses import JSONResponse, Response


app = FastAPI(middleware=[Middleware(UAMiddleware)])


@app.get("/")
async def index(request: Request) -> Response:
    ua = request.scope["ua"]
    data = {
        "ua_string": ua.ua_string,
        "os": ua.os,
        "os.family": ua.os.family,
        "os.version": ua.os.version,
        "os.version_string": ua.os.version_string,
        "browser": ua.browser,
        "browser.family": ua.ua.browser.family,
        "browser.version": ua.ua.browser.version,
        "browser.version_string": ua.ua.browser.version_string,
        "device": ua.device,
        "device.family": ua.device.family,
        "device.brand": ua.device.brand,
        "device.model": ua.device.model,
        "is_provided": ua.is_provided,
        "is_tablet": ua.is_tablet,
        "is_mobile": ua.is_mobile,
        "is_touch_capable": ua.is_touch_capable,
        "is_pc": ua.is_pc,
        "is_bot": ua.is_bot,
        "is_email_client": ua.is_email_client,
    }
    return JSONResponse(data)

API Reference

UAMiddleware

An ASGI middleware that sets scope["ua"] to an instance of UADetails (scope refers to the ASGI scope).

app = UAMiddleware(app)

UADetails

A helper that provides shortcuts for accessing User-Agent request header.

ua = UADetails(scope)
  • ua: UserAgent - The UserAgent instance from the user-agents package.
  • ua_string: str - The user agent string.
  • is_provided: bool - True if the user agent string is provided.
  • os: OperatingSystem - The operating system details of the user agent. It's a named tuple with the following fields:
    • family: str - The family of the operating system.
    • version: str - The version of the operating system.
    • version_string: str - The version of the operating system as a string.
  • browser: Browser - The browser details of the user agent. It's a named tuple with the following fields:
    • family: str - The family of the browser.
    • version: str - The version of the browser.
    • version_string: str - The version of the browser as a string.
  • device: Device - The device details of the user agent. It's a named tuple with the following fields:
    • family: str - The family of the device.
    • brand: str - The brand of the device.
    • model: str - The model of the device.
  • is_tablet: bool - True if the request was made by a tablet.
  • is_mobile: bool - True if the request was made by a mobile device.
  • is_touch_capable: bool - True if the request was made by a touch-capable device.
  • is_pc: bool - True if the request was made by a PC.
  • is_bot: bool - True if the request was made by a bot.
  • is_email_client: bool - True if the request was made by an email client.

UARequest

For Starlette-based frameworks, use this instead of the standard starlette.requests.Request so that code editors understand that request.scope["ua"] contains an UADetails instance:

from asgi_user_agents import UARequest as Request

async def home(request: Request):
    reveal_type(request.scope["ua"])  # Revealed type is 'UADetails'

Development

Clone the repository and cd into the project directory:

git clone https://github.com/hasansezertasan/asgi-user-agents
cd asgi-user-agents

Install hatch, you can follow the instructions here, or simply run the following command:

pipx install hatch

Initialize the environment and install the dependencies:

hatch shell

Initialize pre-commit hooks by running the following command:

pre-commit install

Make your changes on a new branch and run the tests:

hatch test -a

Make sure that the code is typed, linted, and formatted correctly:

hatch run types:all

Stage your changes and commit them:

git add .
git commit -m "Your message"

Push your changes to the repository:

git push

Create a pull request and wait for the review ๐Ÿค“.

Author

Credits

  • This project wouldn't be possible without the user-agents package ๐Ÿ™.
  • The project structure is inspired by the asgi-htmx ๐Ÿš€ package and contains some code snippets from it ๐Ÿ˜… (even this file).

Analysis

License

asgi-user-agents is distributed under the terms of the MIT license.