restcraft


Namerestcraft JSON
Version 0.1.4 PyPI version JSON
download
home_pageNone
SummaryA minimalist Python WSGI framework for building RESTful APIs.
upload_time2024-11-28 03:51:43
maintainerNone
docs_urlNone
authorNone
requires_python>=3.10
licenseMIT
keywords wsgi framework rest api
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # RestCraft

RestCraft is a lightweight, modular framework designed to build modern web applications in Python. It provides essential tools and components to manage HTTP requests, responses, routing, and middleware, allowing you to focus on building features without being overwhelmed by boilerplate code.

### Key Features

- **Zero External Dependencies**: RestCraft is built entirely with Python's standard library, ensuring a minimal footprint and maximum compatibility.
- **Powerful Routing System**: Support for dynamic and static routes, route merging, and modular blueprints for better organization.
- **Request and Response Handling**: A clean and extensible API to manage HTTP requests, responses, cookies, and headers.
- **Pluggable Architecture**: Add plugins to extend functionality with fine-grained control over their application.
- **Built-in Middleware for CORS**: Enable Cross-Origin Resource Sharing with a simple plugin.
- **Exception Handling**: Centralized error handling with customizable exception responses.

Whether you're building a simple API or a large-scale application, RestCraft gives you the flexibility and control you need while staying lightweight and dependency-free.

## Installation

To install **RestCraft**, just pip install:

```bash
pip install restcraft
```

## Getting Started

Here’s a quick example to set up and run a simple **RestCraft** application:

```python
from restcraft import RestCraft, Router, JSONResponse
from restcraft.views import metadata

from .config import configuration

# Define your views
class HelloWorldView:
    @metadata(methods=["GET"])
    def get(self):
        return JSONResponse({"message": "Hello, World!"})

# Set up the application
app = RestCraft(config=configuration)

# Set up the router
router = Router()
router.add_route("/hello", HelloWorldView())
app.register_router(router)

# Run the application using a WSGI server
if __name__ == "__main__":
    from wsgiref.simple_server import make_server
    server = make_server("127.0.0.1", 8000, app)
    print("Serving on http://127.0.0.1:8000")
    server.serve_forever()
```

## Core Concepts

### Routes

RestCraft provides a powerful routing system to map URL paths to specific views. The `Router` class allows you to register routes, handle dynamic parameters, and merge routers for modular and reusable routing logic.

#### Adding Routes

To add a route, use the `add_route` method. Specify the path and the corresponding view object or class:

```python
from restcraft.http.router import Router
from restcraft.http.response import JSONResponse
from restcraft.views import metadata

class MyView:
    @metadata(methods=["GET"])
    def hello(self):
        return JSONResponse({"message": "Hello, World!"})

router = Router()
router.add_route("/hello", MyView())
```

#### Dynamic Routes

Dynamic segments in paths are defined with a `<` prefix and `>` suffix. Dynamic routes allow you to capture parts of the URL and pass them as parameters to the handler:

```python
class UserView:
    @metadata(methods=["GET"])
    def get_user(self, id):
        return JSONResponse({"user_id": id})

router.add_route("/user/<id>", UserView())
router.add_route(r"/user/<id:\d+>", UserView())

# Example:
# GET /user/42 -> {"user_id": "42"}
```

#### Merging Routers

The `merge` function allows you to combine multiple routers into a single router. This enables modular routing, similar to blueprints in other frameworks, making it easy to organize your application by grouping related routes.

```python
# Define a "users" module
users_router = Router(prefix="/users")

class UserView:
    @metadata(methods=["GET"])
    def list_users(self):
        return JSONResponse({"users": []})

    @metadata(methods=["POST"])
    def create_user(self):
        return JSONResponse({"message": "User created"})

users_router.add_route("/", UserView())

# Define a "products" module
products_router = Router(prefix="/products")

class ProductView:
    @metadata(methods=["GET"])
    def list_products(self):
        return JSONResponse({"products": []})

products_router.add_route("/", ProductView())

# Merge modules into the main router
app_router = Router()
app_router.merge(users_router)
app_router.merge(products_router)

# Example:
# GET /users -> {"users": []}
# GET /products -> {"products": []}
```

### Request Handling

Access request properties like headers, query parameters, JSON payloads, forms, and file uploads:

```python
from restcraft.http import request

class UserView:
    @metadata(methods=["POST"])
    def create(self):
        data = request.json
        return JSONResponse({"received": data})
```

### Plugins

Extend functionality using plugins. Plugins in RestCraft are middleware-like components that can modify the behavior of request handlers. Each plugin can be selectively applied to specific methods by using the `metadata` decorator.

#### Using Plugins

To register a plugin, use the `register_plugin` method of the `RestCraft` application:

```python
from restcraft.contrib.plugins.cors_plugin import CORSPlugin

plugin = CORSPlugin(allow_origins=["http://example.com"])
app.register_plugin(plugin)
```

#### Controlling Plugin Execution with Metadata

The `metadata` decorator allows you to specify which plugins should run (or be excluded) for a particular method. By default, all plugins run on all methods unless specified otherwise.

- **Include Plugins**: List plugin names to explicitly allow them.
- **Exclude Plugins**: Prefix the plugin name with `-` to exclude it.

Here’s an example:

```python
from restcraft.http.response import JSONResponse
from restcraft.views import metadata

class MyView:
    # Allow all plugins (default behavior)
    @metadata(methods=["GET"])
    def all_plugins_allowed(self):
        return JSONResponse({"message": "All plugins are allowed"})

    # Only allow 'cors_plugin' to run
    @metadata(methods=["POST"], plugins=["cors_plugin"])
    def only_cors_plugin(self):
        return JSONResponse({"message": "Only CORS plugin will run"})

    # Exclude 'auth_plugin'
    @metadata(methods=["DELETE"], plugins=["...", "-auth_plugin"])
    def exclude_auth_plugin(self):
        return JSONResponse({"message": "All plugins except 'auth_plugin' will run"})
```

#### Writing Your Own Plugin

To create a custom plugin, subclass the `Plugin` class and implement the `before_handler` or `before_route` method:

```python
from restcraft.plugin import Plugin

class CustomHeaderPlugin(Plugin):
    name = "custom_header_plugin"

    def before_handler(self, handler, metadata):
        def wrapper(*args, **kwargs):
            response = handler(*args, **kwargs)
            response.headers["X-Custom-Header"] = "My Custom Value"
            return response
        return wrapper
```

Register your plugin with the application:

```python
plugin = CustomHeaderPlugin()
app.register_plugin(plugin)
```

#### Plugin Execution Order

Plugins are applied in the order they are registered in the application. To control execution order, register plugins in the desired sequence:

```python
app.register_plugin(PluginA())
app.register_plugin(PluginB())
```

## File Uploads

RestCraft handles file uploads efficiently, writing large files to disk-backed temporary storage. Here's how you can access uploaded files:

```python
class FileUploadView:
    @metadata(methods=["POST"])
    def upload(self):
        file_data = request.files.get("file")
        return JSONResponse({
            "filename": file_data["filename"],
            "content_type": file_data["content_type"],
        })
```

## Cookies

RestCraft includes a powerful and flexible cookie management system inspired by [Remix.run](https://remix.run). With RestCraft, you can easily create, parse, sign, and validate cookies, enabling secure state management for your web applications.

### Key Features

- **Serialization and Parsing**: Effortlessly serialize Python objects into cookies and parse them back into Python objects.
- **Signed Cookies**: Use secret keys to sign cookies, ensuring their integrity and protecting against tampering.
- **Expiration and Max-Age**: Automatically manage cookie expiration with built-in support for `Expires` and `Max-Age` attributes.
- **Secure Defaults**: Cookies are configured to be `HttpOnly` and `Secure` by default, ensuring they are protected from client-side scripts and transmitted only over HTTPS.

### Example Usage

#### Creating and Serializing a Cookie

```python
from restcraft.http import Cookie

# Create a new cookie with secure options
cookie = Cookie("user_session", options={"secrets": ["my_secret_key"], "secure": True})

class MyView:

    @metadata(methods=["GET"])
    def list(self):
        # read
        user_info = cookie.parse(request.headers["cookie"])

        # set
        return JSONResponse(data, headers={"Set-Cookie": cookie.serialize(user_info, overrides={"max_age": 60})})
```

## Custom Exception Handling

Define custom exception handlers for your application:

```python
from restcraft.exceptions import RestCraftException

@app.register_exception(RestCraftException)
def handle_restcraft_exception(exc):
    return JSONResponse({"error": exc.message}, status=exc.status)
```

## Contributing

Contributions are welcome! If you'd like to improve RestCraft, follow these steps:

1. Fork the repository.
2. Create a new branch.
3. Make your changes and write tests.
4. Submit a pull request.

## License

This project is licensed under the MIT License. See the `LICENSE` file for details.

## Acknowledgements

Special thanks to all contributors and the Python community for inspiring this project.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "restcraft",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "wsgi, framework, rest, api",
    "author": null,
    "author_email": "Lucas Santana <lsfratel@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/a5/36/047dca5d1694a3d7a77be8644d1025f2ac1f78c3cb2bc468b0217c922316/restcraft-0.1.4.tar.gz",
    "platform": null,
    "description": "# RestCraft\n\nRestCraft is a lightweight, modular framework designed to build modern web applications in Python. It provides essential tools and components to manage HTTP requests, responses, routing, and middleware, allowing you to focus on building features without being overwhelmed by boilerplate code.\n\n### Key Features\n\n- **Zero External Dependencies**: RestCraft is built entirely with Python's standard library, ensuring a minimal footprint and maximum compatibility.\n- **Powerful Routing System**: Support for dynamic and static routes, route merging, and modular blueprints for better organization.\n- **Request and Response Handling**: A clean and extensible API to manage HTTP requests, responses, cookies, and headers.\n- **Pluggable Architecture**: Add plugins to extend functionality with fine-grained control over their application.\n- **Built-in Middleware for CORS**: Enable Cross-Origin Resource Sharing with a simple plugin.\n- **Exception Handling**: Centralized error handling with customizable exception responses.\n\nWhether you're building a simple API or a large-scale application, RestCraft gives you the flexibility and control you need while staying lightweight and dependency-free.\n\n## Installation\n\nTo install **RestCraft**, just pip install:\n\n```bash\npip install restcraft\n```\n\n## Getting Started\n\nHere\u2019s a quick example to set up and run a simple **RestCraft** application:\n\n```python\nfrom restcraft import RestCraft, Router, JSONResponse\nfrom restcraft.views import metadata\n\nfrom .config import configuration\n\n# Define your views\nclass HelloWorldView:\n    @metadata(methods=[\"GET\"])\n    def get(self):\n        return JSONResponse({\"message\": \"Hello, World!\"})\n\n# Set up the application\napp = RestCraft(config=configuration)\n\n# Set up the router\nrouter = Router()\nrouter.add_route(\"/hello\", HelloWorldView())\napp.register_router(router)\n\n# Run the application using a WSGI server\nif __name__ == \"__main__\":\n    from wsgiref.simple_server import make_server\n    server = make_server(\"127.0.0.1\", 8000, app)\n    print(\"Serving on http://127.0.0.1:8000\")\n    server.serve_forever()\n```\n\n## Core Concepts\n\n### Routes\n\nRestCraft provides a powerful routing system to map URL paths to specific views. The `Router` class allows you to register routes, handle dynamic parameters, and merge routers for modular and reusable routing logic.\n\n#### Adding Routes\n\nTo add a route, use the `add_route` method. Specify the path and the corresponding view object or class:\n\n```python\nfrom restcraft.http.router import Router\nfrom restcraft.http.response import JSONResponse\nfrom restcraft.views import metadata\n\nclass MyView:\n    @metadata(methods=[\"GET\"])\n    def hello(self):\n        return JSONResponse({\"message\": \"Hello, World!\"})\n\nrouter = Router()\nrouter.add_route(\"/hello\", MyView())\n```\n\n#### Dynamic Routes\n\nDynamic segments in paths are defined with a `<` prefix and `>` suffix. Dynamic routes allow you to capture parts of the URL and pass them as parameters to the handler:\n\n```python\nclass UserView:\n    @metadata(methods=[\"GET\"])\n    def get_user(self, id):\n        return JSONResponse({\"user_id\": id})\n\nrouter.add_route(\"/user/<id>\", UserView())\nrouter.add_route(r\"/user/<id:\\d+>\", UserView())\n\n# Example:\n# GET /user/42 -> {\"user_id\": \"42\"}\n```\n\n#### Merging Routers\n\nThe `merge` function allows you to combine multiple routers into a single router. This enables modular routing, similar to blueprints in other frameworks, making it easy to organize your application by grouping related routes.\n\n```python\n# Define a \"users\" module\nusers_router = Router(prefix=\"/users\")\n\nclass UserView:\n    @metadata(methods=[\"GET\"])\n    def list_users(self):\n        return JSONResponse({\"users\": []})\n\n    @metadata(methods=[\"POST\"])\n    def create_user(self):\n        return JSONResponse({\"message\": \"User created\"})\n\nusers_router.add_route(\"/\", UserView())\n\n# Define a \"products\" module\nproducts_router = Router(prefix=\"/products\")\n\nclass ProductView:\n    @metadata(methods=[\"GET\"])\n    def list_products(self):\n        return JSONResponse({\"products\": []})\n\nproducts_router.add_route(\"/\", ProductView())\n\n# Merge modules into the main router\napp_router = Router()\napp_router.merge(users_router)\napp_router.merge(products_router)\n\n# Example:\n# GET /users -> {\"users\": []}\n# GET /products -> {\"products\": []}\n```\n\n### Request Handling\n\nAccess request properties like headers, query parameters, JSON payloads, forms, and file uploads:\n\n```python\nfrom restcraft.http import request\n\nclass UserView:\n    @metadata(methods=[\"POST\"])\n    def create(self):\n        data = request.json\n        return JSONResponse({\"received\": data})\n```\n\n### Plugins\n\nExtend functionality using plugins. Plugins in RestCraft are middleware-like components that can modify the behavior of request handlers. Each plugin can be selectively applied to specific methods by using the `metadata` decorator.\n\n#### Using Plugins\n\nTo register a plugin, use the `register_plugin` method of the `RestCraft` application:\n\n```python\nfrom restcraft.contrib.plugins.cors_plugin import CORSPlugin\n\nplugin = CORSPlugin(allow_origins=[\"http://example.com\"])\napp.register_plugin(plugin)\n```\n\n#### Controlling Plugin Execution with Metadata\n\nThe `metadata` decorator allows you to specify which plugins should run (or be excluded) for a particular method. By default, all plugins run on all methods unless specified otherwise.\n\n- **Include Plugins**: List plugin names to explicitly allow them.\n- **Exclude Plugins**: Prefix the plugin name with `-` to exclude it.\n\nHere\u2019s an example:\n\n```python\nfrom restcraft.http.response import JSONResponse\nfrom restcraft.views import metadata\n\nclass MyView:\n    # Allow all plugins (default behavior)\n    @metadata(methods=[\"GET\"])\n    def all_plugins_allowed(self):\n        return JSONResponse({\"message\": \"All plugins are allowed\"})\n\n    # Only allow 'cors_plugin' to run\n    @metadata(methods=[\"POST\"], plugins=[\"cors_plugin\"])\n    def only_cors_plugin(self):\n        return JSONResponse({\"message\": \"Only CORS plugin will run\"})\n\n    # Exclude 'auth_plugin'\n    @metadata(methods=[\"DELETE\"], plugins=[\"...\", \"-auth_plugin\"])\n    def exclude_auth_plugin(self):\n        return JSONResponse({\"message\": \"All plugins except 'auth_plugin' will run\"})\n```\n\n#### Writing Your Own Plugin\n\nTo create a custom plugin, subclass the `Plugin` class and implement the `before_handler` or `before_route` method:\n\n```python\nfrom restcraft.plugin import Plugin\n\nclass CustomHeaderPlugin(Plugin):\n    name = \"custom_header_plugin\"\n\n    def before_handler(self, handler, metadata):\n        def wrapper(*args, **kwargs):\n            response = handler(*args, **kwargs)\n            response.headers[\"X-Custom-Header\"] = \"My Custom Value\"\n            return response\n        return wrapper\n```\n\nRegister your plugin with the application:\n\n```python\nplugin = CustomHeaderPlugin()\napp.register_plugin(plugin)\n```\n\n#### Plugin Execution Order\n\nPlugins are applied in the order they are registered in the application. To control execution order, register plugins in the desired sequence:\n\n```python\napp.register_plugin(PluginA())\napp.register_plugin(PluginB())\n```\n\n## File Uploads\n\nRestCraft handles file uploads efficiently, writing large files to disk-backed temporary storage. Here's how you can access uploaded files:\n\n```python\nclass FileUploadView:\n    @metadata(methods=[\"POST\"])\n    def upload(self):\n        file_data = request.files.get(\"file\")\n        return JSONResponse({\n            \"filename\": file_data[\"filename\"],\n            \"content_type\": file_data[\"content_type\"],\n        })\n```\n\n## Cookies\n\nRestCraft includes a powerful and flexible cookie management system inspired by [Remix.run](https://remix.run). With RestCraft, you can easily create, parse, sign, and validate cookies, enabling secure state management for your web applications.\n\n### Key Features\n\n- **Serialization and Parsing**: Effortlessly serialize Python objects into cookies and parse them back into Python objects.\n- **Signed Cookies**: Use secret keys to sign cookies, ensuring their integrity and protecting against tampering.\n- **Expiration and Max-Age**: Automatically manage cookie expiration with built-in support for `Expires` and `Max-Age` attributes.\n- **Secure Defaults**: Cookies are configured to be `HttpOnly` and `Secure` by default, ensuring they are protected from client-side scripts and transmitted only over HTTPS.\n\n### Example Usage\n\n#### Creating and Serializing a Cookie\n\n```python\nfrom restcraft.http import Cookie\n\n# Create a new cookie with secure options\ncookie = Cookie(\"user_session\", options={\"secrets\": [\"my_secret_key\"], \"secure\": True})\n\nclass MyView:\n\n    @metadata(methods=[\"GET\"])\n    def list(self):\n        # read\n        user_info = cookie.parse(request.headers[\"cookie\"])\n\n        # set\n        return JSONResponse(data, headers={\"Set-Cookie\": cookie.serialize(user_info, overrides={\"max_age\": 60})})\n```\n\n## Custom Exception Handling\n\nDefine custom exception handlers for your application:\n\n```python\nfrom restcraft.exceptions import RestCraftException\n\n@app.register_exception(RestCraftException)\ndef handle_restcraft_exception(exc):\n    return JSONResponse({\"error\": exc.message}, status=exc.status)\n```\n\n## Contributing\n\nContributions are welcome! If you'd like to improve RestCraft, follow these steps:\n\n1. Fork the repository.\n2. Create a new branch.\n3. Make your changes and write tests.\n4. Submit a pull request.\n\n## License\n\nThis project is licensed under the MIT License. See the `LICENSE` file for details.\n\n## Acknowledgements\n\nSpecial thanks to all contributors and the Python community for inspiring this project.\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A minimalist Python WSGI framework for building RESTful APIs.",
    "version": "0.1.4",
    "project_urls": {
        "source": "https://github.com/lsfratel/restcraft"
    },
    "split_keywords": [
        "wsgi",
        " framework",
        " rest",
        " api"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "3b15b709276c72657e896f78a4fc16bfc34cf49c3e77a1dd48ceb7d4df483e00",
                "md5": "c5a088276a6912edd75b1e3a88fbce04",
                "sha256": "b28f6a48b53982e415c9cb1400157eb793d9a4aca089e62d149d3fb93d394590"
            },
            "downloads": -1,
            "filename": "restcraft-0.1.4-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "c5a088276a6912edd75b1e3a88fbce04",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 24453,
            "upload_time": "2024-11-28T03:51:41",
            "upload_time_iso_8601": "2024-11-28T03:51:41.808446Z",
            "url": "https://files.pythonhosted.org/packages/3b/15/b709276c72657e896f78a4fc16bfc34cf49c3e77a1dd48ceb7d4df483e00/restcraft-0.1.4-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "a536047dca5d1694a3d7a77be8644d1025f2ac1f78c3cb2bc468b0217c922316",
                "md5": "c21212e6dbce46a69f4a3fab75eafc02",
                "sha256": "017fbdb3bc7fdca3a03fdaeb9ec864aa10b5af7ef56bb3b5023c4a26bfde6a43"
            },
            "downloads": -1,
            "filename": "restcraft-0.1.4.tar.gz",
            "has_sig": false,
            "md5_digest": "c21212e6dbce46a69f4a3fab75eafc02",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 24634,
            "upload_time": "2024-11-28T03:51:43",
            "upload_time_iso_8601": "2024-11-28T03:51:43.720208Z",
            "url": "https://files.pythonhosted.org/packages/a5/36/047dca5d1694a3d7a77be8644d1025f2ac1f78c3cb2bc468b0217c922316/restcraft-0.1.4.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-11-28 03:51:43",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "lsfratel",
    "github_project": "restcraft",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "restcraft"
}
        
Elapsed time: 0.76842s