You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在VPS上仅用Golang工具配置htaccess(无需Nginx/Apache)

Replicating .htaccess Functionality with Go on Your VPS

Alright, let's figure out how to get that .htaccess-style functionality working with just Go on your VPS—no Apache or Nginx required. Here's a practical breakdown of how to replicate common .htaccess features using Go's standard library or lightweight routing tools:

Core Idea

.htaccess is mostly used for URL rewrites, redirects, HTTP header management, and access control. Since Go can act as a full-featured HTTP server on its own, we can replicate all these behaviors directly in your Go code, either with the standard net/http package or a lightweight routing library like gorilla/mux (it's a popular Go-specific tool, so it fits your "only Golang tools" goal).


Common .htaccess Features & Their Go Equivalents

1. URL Rewrites (Clean URLs)

If you’re using clean URLs (like rewriting /blog/post/123 to /blog/post?id=123), here’s how to do it:

With Go's Standard Library

package main

import (
	"net/http"
	"strings"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		// Rewrite /blog/post/[id] to /blog/post with id query param
		if strings.HasPrefix(r.URL.Path, "/blog/post/") {
			postID := strings.TrimPrefix(r.URL.Path, "/blog/post/")
			r.URL.Path = "/blog/post"
			r.URL.RawQuery = "id=" + postID + "&" + r.URL.RawQuery
			// Forward to the actual handler
			blogPostHandler(w, r)
		} else {
			// Serve static files from your public directory
			http.ServeFile(w, r, "public"+r.URL.Path)
		}
	})

	http.ListenAndServe(":8080", nil)
}

func blogPostHandler(w http.ResponseWriter, r *http.Request) {
	postID := r.URL.Query().Get("id")
	w.Write([]byte("Blog Post ID: " + postID))
}

With gorilla/mux (Simpler for Complex Routes)

package main

import (
	"net/http"
	"github.com/gorilla/mux"
)

func main() {
	r := mux.NewRouter()
	// Define the "clean" route directly as the handler
	r.HandleFunc("/blog/post/{id}", blogPostHandler).Methods("GET")

	// Serve static files from the public folder
	r.PathPrefix("/").Handler(http.FileServer(http.Dir("public")))

	http.ListenAndServe(":8080", r)
}

func blogPostHandler(w http.ResponseWriter, r *http.Request) {
	vars := mux.Vars(r)
	postID := vars["id"]
	w.Write([]byte("Blog Post ID: " + postID))
}

2. 301/302 Redirects

For permanent (301) or temporary (302) redirects (like .htaccess's Redirect 301 /old-page /new-page):

// Using standard library
http.HandleFunc("/old-page", func(w http.ResponseWriter, r *http.Request) {
	// 301 permanent redirect
	http.Redirect(w, r, "/new-page", http.StatusMovedPermanently)
	// Use http.StatusFound for 302 temporary redirect
})

// With gorilla/mux
r.HandleFunc("/old-page", func(w http.ResponseWriter, r *http.Request) {
	http.Redirect(w, r, "/new-page", http.StatusMovedPermanently)
})

3. Setting HTTP Headers

To add security or caching headers (like .htaccess's Header set X-Content-Type-Options nosniff), use middleware:

func addSecurityHeaders(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("X-Content-Type-Options", "nosniff")
		w.Header().Set("Cache-Control", "max-age=3600")
		w.Header().Set("X-Frame-Options", "DENY")
		// Pass the request to the next handler
		next.ServeHTTP(w, r)
	})
}

// Apply middleware to your entire router
func main() {
	r := mux.NewRouter()
	// ... define your routes ...

	// Wrap the router with the header middleware
	http.ListenAndServe(":8080", addSecurityHeaders(r))
}

4. Access Control (Allow/Deny IPs)

To restrict access to specific IPs (like .htaccess's Allow from 192.168.1.1):

func restrictIPs(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		allowedIPs := []string{"192.168.1.1", "10.0.0.5"}
		// Extract client IP (strip port number)
		clientIP := strings.Split(r.RemoteAddr, ":")[0]

		allowed := false
		for _, ip := range allowedIPs {
			if ip == clientIP {
				allowed = true
				break
			}
		}

		if !allowed {
			http.Error(w, "Forbidden", http.StatusForbidden)
			return
		}

		next.ServeHTTP(w, r)
	})
}

// Apply to a specific route (e.g., admin panel)
r.HandleFunc("/admin", adminHandler).Methods("GET").Middleware(restrictIPs)

Deployment on Your VPS

Once your code is ready, here’s how to deploy it reliably:

  1. Build the binary for your VPS:
    # For 64-bit Linux VPS
    GOOS=linux GOARCH=amd64 go build -o mywebapp
    # For ARM64 VPS (e.g., AWS Graviton)
    GOOS=linux GOARCH=arm64 go build -o mywebapp
    
  2. Transfer the binary to your VPS:
    scp mywebapp your-user@your-vps-ip:/var/www/mywebapp/
    
  3. Run as a system service (so it starts on boot and restarts if it crashes):
    Create a systemd service file at /etc/systemd/system/mywebapp.service:
    [Unit]
    Description=My Go Web Application
    After=network.target
    
    [Service]
    User=www-data
    WorkingDirectory=/var/www/mywebapp
    ExecStart=/var/www/mywebapp/mywebapp
    Restart=always
    
    [Install]
    WantedBy=multi-user.target
    
    Then enable and start the service:
    sudo systemctl daemon-reload
    sudo systemctl enable mywebapp
    sudo systemctl start mywebapp
    
  4. Bind to port 80/443 (standard HTTP/HTTPS ports):
    Instead of running with sudo, use setcap to let the binary bind to privileged ports:
    sudo setcap CAP_NET_BIND_SERVICE=+eip /var/www/mywebapp/mywebapp
    
    Then update your code to listen on :80 or :443.

内容的提问来源于stack exchange,提问作者TalkingJson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:19:44