router / README.md
waxiangzi's picture
Update README.md
bc1c384 verified
metadata
title: Basic Docker SDK Space
emoji: 🐳
colorFrom: purple
colorTo: gray
sdk: docker
app_port: 8000

用bun+ts+http-proxy实现一个用完整的url作为path参数,反向代理此path的url来访问api的功能,要求支持至少16个并发请求

示例:

Project Setup:

  1. Create Project Directory:

    mkdir bun-url-proxy
    cd bun-url-proxy
    
  2. Initialize Bun Project:

    bun init -y
    

    (Follow the prompts, the defaults are usually fine. Ensure index.ts is your entry point).

  3. Create src directory and index.ts file:

Explanation:

  1. Bun Server (serve): Sets up a high-performance HTTP server listening on localhost:8001.
  2. Fetch Handler: This function is called for every incoming request.
  3. URL Extraction:
    • It takes the pathname from the incoming request URL (request.url).
    • url.pathname.substring(1) removes the leading /.
    • + url.search appends any query parameters from the original proxy request to the target URL.
  4. URL Validation: It uses a try...catch block with new URL() to ensure the extracted path is actually a valid URL structure. If not, it returns a 400 Bad Request.
  5. Header Forwarding:
    • It iterates through the incoming request's headers.
    • It copies headers to a new Headers object (forwardedHeaders), skipping common hop-by-hop headers defined in BANNED_HEADERS (like Connection, Keep-Alive, Host, etc.). It's crucial not to forward the original Host header; fetch will set the correct Host based on the targetUrl.
    • It adds X-Forwarded-For, X-Forwarded-Host, and X-Forwarded-Proto headers, which are standard practice for proxies to inform the target server about the original client request.
  6. Making the Proxy Request (fetch):
    • It uses Bun's built-in fetch to make the actual request to the targetUrl.
    • method: Copies the original request method.
    • headers: Uses the filtered forwardedHeaders.
    • body: Forwards the request body only if the method isn't GET or HEAD and if a body exists (request.body).
    • redirect: 'manual': This is very important. It tells fetch not to follow redirects (3xx responses) itself. Instead, it will return the 3xx response, which the proxy then sends back to the original client. This allows the client's browser or application to handle the redirect correctly.
  7. Handling the Response:
    • It takes the Response object (proxyResponse) received from the target server.
    • It creates new response headers, copying headers from the proxyResponse while again filtering out hop-by-hop headers using BANNED_HEADERS. This prevents sending invalid headers back to the client.
    • It constructs a new Response to send back to the original client, using the target's status code, status text, the filtered headers, and crucially, the proxyResponse.body. This streams the body efficiently from the target to the client.
  8. Error Handling:
    • A try...catch block surrounds the fetch call to handle network errors (e.g., DNS resolution failure, connection refused). It logs the error and returns a 502 Bad Gateway or 504 Gateway Timeout response.
    • The server.error handler catches broader server errors.
  9. Concurrency: Bun's server and fetch implementation are built on an asynchronous, event-driven architecture (similar to Node.js but often faster). It's designed for high concurrency out-of-the-box. Handling 16 concurrent requests should be trivial for Bun on reasonably modern hardware, assuming the target servers can also handle that load. No special code is needed in this application to enable concurrency; Bun manages it.
  10. Graceful Shutdown: Listens for SIGINT (Ctrl+C) and SIGTERM to shut down the server cleanly.

How to Run:

Running Locally

  1. Save the code as src/index.ts.
  2. Run from your terminal in the project directory:
    bun start
    # Or for development with automatic restarts on file changes:
    # bun run dev
    

Running with Docker

Using Docker directly

  1. Build the Docker image:

    docker build -t proxy-url .
    
  2. Run the container:

    docker run -p 8001:8001 proxy-url
    

Using Docker Compose

  1. Start the service:

    docker-compose up -d
    
  2. View logs:

    docker-compose logs -f
    
  3. Stop the service:

    docker-compose down
    

How to Use:

Open your browser or use curl:

  • http://localhost:8001/https://httpbin.org/get?show_env=1 (Proxies to httpbin's get endpoint)
  • http://localhost:8001/https://api.github.com/users/octocat (Proxies to GitHub API)
  • curl -X POST -H "Content-Type: application/json" -d '{"name":"proxy test"}' http://localhost:8001/https://httpbin.org/post (Proxies a POST request)

The server will log the requests and proxy actions to the console.

Docker Deployment

This project includes Docker configuration for easy deployment:

  • Dockerfile: Defines the container image using the official Bun image
  • docker-compose.yml: Provides an easy way to run the container with proper configuration
  • .dockerignore: Excludes unnecessary files from the Docker build context

Docker Image Features

  • Uses the official Bun Docker image for optimal performance
  • Properly handles dependencies installation
  • Exposes port 8001 for the proxy service
  • Configures environment variables for production use
  • Includes a health check to ensure the service is running properly

Multi-stage Build

The Dockerfile uses a multi-stage build approach to keep the final image size small and efficient.

Container Security

The Docker configuration follows best practices for container security:

  • Uses a specific version of the Bun image rather than 'latest'
  • Runs as a non-root user when possible
  • Minimizes the number of layers and installed dependencies