Chapter 3 · CORE

HTTP API & Routing

📄 03_http_api___routing.md 🏷 Core

Chapter 3: HTTP API & Routing

Welcome back!

In Chapter 1: File System & Indexing, we built the library infrastructure to manage files. In Chapter 2: Authentication & User Storage, we hired a security guard to check IDs.

But right now, our application is just a collection of silent code. It sits there waiting. It doesn't know how to talk to the outside world.

In this chapter, we will build the Receptionist. We will set up the web server that answers the phone, listens to requests from the browser, checks with the security guard, and directs the request to the right department.

The Problem: The "Silent" Application

Your browser speaks HTTP (HyperText Transfer Protocol). It sends messages like:

Without an HTTP Server and a Router, our Go code doesn't hear these messages. We need a system to translate a URL (like filebrowser.com/api/resources) into a specific Go function execution.

The Solution: The Router & The Handlers

Filebrowser uses the standard Go library to handle this.

  1. The Server: Listens on a specific port (like :8080) for incoming signals.
  2. The Router (ServeMux): Acts as the traffic controller. It looks at the URL and points to the right direction.
  3. The Handler: The specific function that does the work (e.g., deleteFile).
  4. Middleware: layers wrapped around the handler (like logging or auth checks).

Key Concepts

1. The Router (http.ServeMux)

Think of the Router as a phone directory. It maps a "Path" to an "Action".

2. Middleware (The Wrappers)

Middleware is code that runs before the main action. In Chapter 2, we created the authentication logic. In this chapter, we wrap our API routes in a middleware called withUser.

3. The Handler

This is the end of the line. The handler takes the request, talks to the File System (Chapter 1), and sends back a JSON response (data formatted for the web).


How it Works: A Use Case

Let's look at the most common scenario: The frontend asks to see the files in a folder.

  1. Request: Browser sends GET /api/resources?path=/photos.
  2. Routing: The server sees /api/resources and directs traffic to the resourceGetHandler.
  3. Middleware: The withUser wrapper ensures the user is logged in.
  4. Execution: The handler asks the Index for the file list.
  5. Response: The handler sends back a JSON list: [{"name": "vacation.jpg"}, ...].

Usage Example: Defining Routes

In backend/http/httpRouter.go, we define the rules for our traffic controller.

// backend/http/httpRouter.go

// Create a new router
api := http.NewServeMux()

// Define a rule: When "GET /resources" is called...
// 1. Run 'withUser' (Middleware to check security)
// 2. Then run 'resourceGetHandler' (The actual logic)
api.HandleFunc("GET /resources", withUser(resourceGetHandler))

// Define a rule for Deleting
api.HandleFunc("DELETE /resources", withUser(resourceDeleteHandler))

Explanation:


Code Walkthrough: The "Get Resources" Handler

Once the router accepts the request and the middleware approves the user, the resourceGetHandler runs. This is where we connect to Chapter 1.

// backend/http/resource.go

func resourceGetHandler(w http.ResponseWriter, r *http.Request, d *requestContext) (int, error) {
    // 1. Read the requested path from the URL (e.g., /photos)
    path := r.URL.Query().Get("path")
    
    // 2. Call the File System (from Chapter 1) to get the data
    fileInfo, err := files.FileInfoFaster(utils.FileOptions{
        Path:   path,
        Source: r.URL.Query().Get("source"),
    }, store.Access, d.user)

    // 3. Convert the Go struct into JSON and send it back to the browser
    return renderJSON(w, r, fileInfo)
}

Explanation:

  1. r.URL.Query().Get("path"): Extracts ?path=/photos from the URL.
  2. files.FileInfoFaster: This is the "Librarian" from Chapter 1. It looks up the files in the Index.
  3. renderJSON: A helper that formats the result so the JavaScript frontend can understand it.

Under the Hood: The Request Lifecycle

What exactly happens from the moment you press "Enter" in the browser?

The Flow Diagram

sequenceDiagram participant B as Browser participant R as Router (Mux) participant M as Middleware (Auth) participant H as Handler (Resource) participant FS as File System B->>R: GET /api/resources?path=/docs R->>M: Route Found! Check Security. alt Not Logged In M-->>B: 401 Unauthorized (Stop) else Logged In M->>H: Pass Request H->>FS: Get file info for "/docs" FS-->>H: Return file list H-->>B: Return JSON (200 OK) end

Deep Dive: Starting the Server

The application entry point is StartHttp. This function turns the lights on.

// backend/http/httpRouter.go

func StartHttp(ctx context.Context, storage *bolt.BoltStore, ...) {
    // 1. Initialize the router
    router := http.NewServeMux()
    
    // 2. Setup the server settings (Port, Address)
    srv := &http.Server{
        Addr:    ":8080", // Listens on port 8080
        Handler: router,  // Use our router to handle traffic
    }

    // 3. Start listening (this blocks the program and keeps it running)
    go func() {
        srv.ListenAndServe()
    }()
    
    // 4. Wait for a shutdown signal (Ctrl+C)
    <-ctx.Done()
}

Explanation:

Deep Dive: Handling Uploads (POST)

Handling an upload is slightly more complex because data is streaming in.

// backend/http/resource.go

func resourcePostHandler(w http.ResponseWriter, r *http.Request, d *requestContext) (int, error) {
    // 1. Get destination path
    path := r.URL.Query().Get("path") // e.g., /photos/new_image.jpg

    // 2. Check Permissions (Authorization)
    if !d.user.Permissions.Create {
        return http.StatusForbidden, fmt.Errorf("you can't create files")
    }

    // 3. Stream the file directly from the HTTP body to the disk
    // (This uses the WriteFile function we saw in Chapter 1)
    err := files.WriteFile(source, path, r.Body)
    
    return http.StatusOK, nil
}

Explanation:


Summary

In this chapter, we connected the brain (File System) and the security (Auth) to the outside world.

  1. The Router directs URLs to specific functions.
  2. Middleware ensures that only authenticated users pass through.
  3. Handlers coordinate the logic, calling the File System and returning JSON to the browser.

Now that the backend is fully functional—it can store files, secure users, and answer network requests—we need to control how it starts up and behaves on different computers.

Next Chapter: Configuration & Startup


Generated by Code IQ