Endpoint Generator

The endpoint generator creates HTTP request handlers for your Azu application. Endpoints are the controllers that handle incoming HTTP requests and return responses.

Overview

azu generate endpoint <name> [options]

Basic Usage

Generate a Simple Endpoint

# Generate a basic endpoint
azu generate endpoint users

# Generate with namespace
azu generate endpoint admin/users

# Generate API endpoint
azu generate endpoint api/v1/users --api

Generate CRUD Endpoints

# Generate full CRUD operations
azu generate endpoint posts --actions index,show,create,update,destroy

# Generate specific actions only
azu generate endpoint comments --actions index,create

Command Options

Option
Description
Default

--api

Generate API-only endpoints (no pages/templates)

false

--actions <list>

Specify which actions to generate

all CRUD actions

--skip-tests

Don't generate test files

false

--skip-routes

Don't register routes automatically

false

--force

Overwrite existing files

false

Generated Files

Basic Endpoint Structure

src/endpoints/
└── users/
    ├── index_endpoint.cr      # List all users
    ├── show_endpoint.cr       # Show single user
    ├── new_endpoint.cr        # New user form
    ├── create_endpoint.cr     # Create user
    ├── edit_endpoint.cr       # Edit user form
    ├── update_endpoint.cr     # Update user
    └── destroy_endpoint.cr    # Delete user

API Endpoint Structure

src/endpoints/
└── api/
    └── v1/
        └── users/
            ├── index_endpoint.cr      # GET /api/v1/users
            ├── show_endpoint.cr       # GET /api/v1/users/:id
            ├── create_endpoint.cr     # POST /api/v1/users
            ├── update_endpoint.cr     # PUT /api/v1/users/:id
            └── destroy_endpoint.cr    # DELETE /api/v1/users/:id

Endpoint Types

Web Endpoints (Default)

Full-stack endpoints that render HTML pages and handle form submissions.

Generated Files:

  • Endpoint classes with HTML rendering

  • Associated page components

  • Form handling and validation

  • Flash messages and redirects

Example:

# src/endpoints/users/index_endpoint.cr
class Users::IndexEndpoint < Azu::Endpoint
  def call
    users = User.all
    render "users/index_page", users: users
  end
end

API Endpoints (--api)

JSON API endpoints for building APIs, mobile backends, or microservices.

Generated Files:

  • Endpoint classes with JSON responses

  • Request/response contracts

  • Status codes and error handling

  • No HTML templates

Example:

# src/endpoints/api/v1/users/index_endpoint.cr
class Api::V1::Users::IndexEndpoint < Azu::Endpoint
  def call
    users = User.all
    json users: users.map(&.to_json)
  end
end

Action Types

Index Action

Lists all resources.

# Generate index action
azu generate endpoint users --actions index

Generated Code:

# src/endpoints/users/index_endpoint.cr
class Users::IndexEndpoint < Azu::Endpoint
  def call
    users = User.all
    render "users/index_page", users: users
  end
end

Route: GET /users

Show Action

Displays a single resource.

# Generate show action
azu generate endpoint users --actions show

Generated Code:

# src/endpoints/users/show_endpoint.cr
class Users::ShowEndpoint < Azu::Endpoint
  def call
    user = User.find(params["id"])
    render "users/show_page", user: user
  rescue CQL::RecordNotFound
    not_found
  end
end

Route: GET /users/:id

New Action

Displays form for creating a new resource.

# Generate new action
azu generate endpoint users --actions new

Generated Code:

# src/endpoints/users/new_endpoint.cr
class Users::NewEndpoint < Azu::Endpoint
  def call
    user = User.new
    render "users/new_page", user: user
  end
end

Route: GET /users/new

Create Action

Handles form submission to create a new resource.

# Generate create action
azu generate endpoint users --actions create

Generated Code:

# src/endpoints/users/create_endpoint.cr
class Users::CreateEndpoint < Azu::Endpoint
  def call
    user = User.new(user_params)

    if user.save
      redirect_to "/users/#{user.id}", flash: { success: "User created successfully" }
    else
      render "users/new_page", user: user, status: :unprocessable_entity
    end
  end

  private def user_params
    params.require(:user).permit(:name, :email)
  end
end

Route: POST /users

Edit Action

Displays form for editing an existing resource.

# Generate edit action
azu generate endpoint users --actions edit

Generated Code:

# src/endpoints/users/edit_endpoint.cr
class Users::EditEndpoint < Azu::Endpoint
  def call
    user = User.find(params["id"])
    render "users/edit_page", user: user
  rescue CQL::RecordNotFound
    not_found
  end
end

Route: GET /users/:id/edit

Update Action

Handles form submission to update an existing resource.

# Generate update action
azu generate endpoint users --actions update

Generated Code:

# src/endpoints/users/update_endpoint.cr
class Users::UpdateEndpoint < Azu::Endpoint
  def call
    user = User.find(params["id"])

    if user.update(user_params)
      redirect_to "/users/#{user.id}", flash: { success: "User updated successfully" }
    else
      render "users/edit_page", user: user, status: :unprocessable_entity
    end
  rescue CQL::RecordNotFound
    not_found
  end

  private def user_params
    params.require(:user).permit(:name, :email)
  end
end

Route: PUT /users/:id or PATCH /users/:id

Destroy Action

Deletes a resource.

# Generate destroy action
azu generate endpoint users --actions destroy

Generated Code:

# src/endpoints/users/destroy_endpoint.cr
class Users::DestroyEndpoint < Azu::Endpoint
  def call
    user = User.find(params["id"])
    user.destroy

    redirect_to "/users", flash: { success: "User deleted successfully" }
  rescue CQL::RecordNotFound
    not_found
  end
end

Route: DELETE /users/:id

Examples

Blog Application

# Generate blog endpoints
azu generate endpoint posts
azu generate endpoint comments
azu generate endpoint categories

# Generate admin endpoints
azu generate endpoint admin/dashboard
azu generate endpoint admin/users

API Service

# Generate API endpoints
azu generate endpoint api/v1/users --api
azu generate endpoint api/v1/posts --api
azu generate endpoint api/v1/comments --api

# Generate specific actions
azu generate endpoint api/v1/auth --api --actions create

Nested Resources

# Generate nested endpoints
azu generate endpoint posts/comments
azu generate endpoint users/posts

Generated Code Examples

Web Endpoint (Full CRUD)

# src/endpoints/users/index_endpoint.cr
class Users::IndexEndpoint < Azu::Endpoint
  def call
    users = User.all
    render "users/index_page", users: users
  end
end

# src/endpoints/users/show_endpoint.cr
class Users::ShowEndpoint < Azu::Endpoint
  def call
    user = User.find(params["id"])
    render "users/show_page", user: user
  rescue CQL::RecordNotFound
    not_found
  end
end

# src/endpoints/users/create_endpoint.cr
class Users::CreateEndpoint < Azu::Endpoint
  def call
    user = User.new(user_params)

    if user.save
      redirect_to "/users/#{user.id}", flash: { success: "User created successfully" }
    else
      render "users/new_page", user: user, status: :unprocessable_entity
    end
  end

  private def user_params
    params.require(:user).permit(:name, :email, :password)
  end
end

API Endpoint

# src/endpoints/api/v1/users/index_endpoint.cr
class Api::V1::Users::IndexEndpoint < Azu::Endpoint
  def call
    users = User.all
    json users: users.map(&.to_json)
  end
end

# src/endpoints/api/v1/users/show_endpoint.cr
class Api::V1::Users::ShowEndpoint < Azu::Endpoint
  def call
    user = User.find(params["id"])
    json user: user.to_json
  rescue CQL::RecordNotFound
    json error: "User not found", status: :not_found
  end
end

# src/endpoints/api/v1/users/create_endpoint.cr
class Api::V1::Users::CreateEndpoint < Azu::Endpoint
  def call
    user = User.new(user_params)

    if user.save
      json user: user.to_json, status: :created
    else
      json errors: user.errors, status: :unprocessable_entity
    end
  end

  private def user_params
    params.require(:user).permit(:name, :email, :password)
  end
end

Route Registration

Automatic Route Registration

By default, endpoints are automatically registered in your routes:

# src/server.cr (auto-generated)
require "./endpoints/**"

# Routes are automatically registered based on endpoint structure
# GET /users -> Users::IndexEndpoint
# GET /users/:id -> Users::ShowEndpoint
# GET /users/new -> Users::NewEndpoint
# POST /users -> Users::CreateEndpoint
# GET /users/:id/edit -> Users::EditEndpoint
# PUT /users/:id -> Users::UpdateEndpoint
# DELETE /users/:id -> Users::DestroyEndpoint

Manual Route Registration

If you use --skip-routes, register routes manually:

# src/server.cr
require "./endpoints/**"

# Manual route registration
Azu::Router.draw do
  get "/users", Users::IndexEndpoint
  get "/users/:id", Users::ShowEndpoint
  get "/users/new", Users::NewEndpoint
  post "/users", Users::CreateEndpoint
  get "/users/:id/edit", Users::EditEndpoint
  put "/users/:id", Users::UpdateEndpoint
  delete "/users/:id", Users::DestroyEndpoint
end

Testing

Generated Test Files

# spec/endpoints/users/index_endpoint_spec.cr
require "../spec_helper"

describe Users::IndexEndpoint do
  it "lists all users" do
    user1 = User.create!(name: "John", email: "john@example.com")
    user2 = User.create!(name: "Jane", email: "jane@example.com")

    response = get "/users"

    response.status_code.should eq(200)
    response.body.should contain("John")
    response.body.should contain("Jane")
  end
end

API Endpoint Tests

# spec/endpoints/api/v1/users/index_endpoint_spec.cr
require "../spec_helper"

describe Api::V1::Users::IndexEndpoint do
  it "returns users as JSON" do
    user = User.create!(name: "John", email: "john@example.com")

    response = get "/api/v1/users"

    response.status_code.should eq(200)
    response.headers["Content-Type"].should contain("application/json")

    json = JSON.parse(response.body)
    json["users"].as_a.size.should eq(1)
    json["users"][0]["name"].should eq("John")
  end
end

Advanced Usage

Custom Endpoint Logic

# Generate endpoint with custom actions
azu generate endpoint search --actions index
# src/endpoints/search/index_endpoint.cr
class Search::IndexEndpoint < Azu::Endpoint
  def call
    query = params["q"]?
    results = if query
      User.where("name ILIKE ?", "%#{query}%")
    else
      User.none
    end

    render "search/index_page", results: results, query: query
  end
end

Nested Resources

# Generate nested endpoints
azu generate endpoint posts/comments
# src/endpoints/posts/comments/index_endpoint.cr
class Posts::Comments::IndexEndpoint < Azu::Endpoint
  def call
    post = Post.find(params["post_id"])
    comments = post.comments
    render "posts/comments/index_page", post: post, comments: comments
  rescue CQL::RecordNotFound
    not_found
  end
end

API Versioning

# Generate versioned API endpoints
azu generate endpoint api/v1/users --api
azu generate endpoint api/v2/users --api
# src/endpoints/api/v1/users/index_endpoint.cr
class Api::V1::Users::IndexEndpoint < Azu::Endpoint
  def call
    users = User.all
    json users: users.map(&.to_json_v1)
  end
end

# src/endpoints/api/v2/users/index_endpoint.cr
class Api::V2::Users::IndexEndpoint < Azu::Endpoint
  def call
    users = User.all
    json users: users.map(&.to_json_v2)
  end
end

Best Practices

1. Naming Conventions

# Use plural names for resource endpoints
azu generate endpoint users        # Good
azu generate endpoint user         # Avoid

# Use descriptive names for action endpoints
azu generate endpoint search       # Good
azu generate endpoint dashboard    # Good

2. API Design

# Use consistent API structure
azu generate endpoint api/v1/users --api
azu generate endpoint api/v1/posts --api
azu generate endpoint api/v1/comments --api

# Use versioning for API changes
azu generate endpoint api/v2/users --api

3. Security

# Always validate parameters
private def user_params
  params.require(:user).permit(:name, :email, :password)
end

# Handle errors gracefully
rescue CQL::RecordNotFound
  not_found

4. Testing

# Generate tests for all endpoints
azu generate endpoint users --skip-tests=false

# Test API endpoints with proper status codes
# Test web endpoints with proper redirects

Troubleshooting

Endpoint Not Found

# Check if endpoint was generated
ls -la src/endpoints/

# Check route registration
cat src/server.cr

# Restart server
azu serve

Parameter Issues

# Debug parameters
def call
  puts "Params: #{params.inspect}"
  # ... rest of endpoint
end

Template Issues

# Check if templates exist
ls -la src/pages/

# Generate missing templates
azu generate page users/index

The endpoint generator creates the HTTP request handlers for your Azu application, providing both web and API endpoints with full CRUD operations.

Next Steps:

Last updated