Files
tunnel-please/http/http.go
2025-02-07 21:21:29 +07:00

180 lines
3.9 KiB
Go

package httpServer
import (
"bufio"
"fmt"
"io"
"log"
"net"
"net/http"
"os"
"strings"
"tunnel_pls/session"
"tunnel_pls/utils"
indexView "tunnel_pls/view/index"
)
type RouteHandler http.HandlerFunc
// Simple Router Struct
type Router struct {
routes map[string]map[string]http.Handler
}
// NewRouter initializes a new router
func NewRouter() *Router {
return &Router{
routes: make(map[string]map[string]http.Handler),
}
}
// Handle registers a route with an http.Handler
func (r *Router) Handle(method, path string, handler http.Handler) {
if _, exists := r.routes[method]; !exists {
r.routes[method] = make(map[string]http.Handler)
}
r.routes[method][path] = handler
}
// HandleFunc registers a route with a function
func (r *Router) HandleFunc(method, path string, handlerFunc func(http.ResponseWriter, *http.Request)) {
r.Handle(method, path, http.HandlerFunc(handlerFunc))
}
func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
if methodRoutes, exists := r.routes[req.Method]; exists {
if handler, exists := methodRoutes[req.URL.Path]; exists {
handler.ServeHTTP(w, req)
return
}
}
http.Error(w, "404 Not Found", http.StatusNotFound)
}
type tcpResponseWriter struct {
conn net.Conn
header http.Header
status int
}
func (w *tcpResponseWriter) Header() http.Header {
return w.header
}
func (w *tcpResponseWriter) WriteHeader(statusCode int) {
w.status = statusCode
}
func (w *tcpResponseWriter) Write(data []byte) (int, error) {
fmt.Println("here")
resp := fmt.Sprintf("HTTP/1.1 %d %s\r\n", w.status, http.StatusText(w.status))
for k, v := range w.header {
resp += fmt.Sprintf("%s: %s\r\n", k, v[0])
}
resp += "\r\n" + string(data)
return w.conn.Write([]byte(resp))
}
var router = NewRouter()
func Listen() {
server, err := net.Listen("tcp", ":80")
if err != nil {
log.Fatal(err)
return
}
router.HandleFunc("GET", "/", func(w http.ResponseWriter, r *http.Request) {
indexView.Main("Main Page", utils.Getenv("domain")).Render(r.Context(), w)
return
})
router.HandleFunc("GET", "/public/output.css", func(w http.ResponseWriter, r *http.Request) {
open, err := os.Open("public/output.css")
if err != nil {
return
}
data, _ := io.ReadAll(open)
fmt.Fprintf(w, string(data))
})
//fileserver := http.FileServer(http.Dir("./public"))
//router.Handle("/public/", http.StripPrefix("/public", fileserver))
defer server.Close()
log.Println("Listening on :80")
for {
conn, err := server.Accept()
if err != nil {
log.Fatal(err)
return
}
go handleRequest(conn)
}
}
func handleRequest(conn net.Conn) {
defer conn.Close()
var rawRequest string
reader := bufio.NewReader(conn)
r, err := http.ReadRequest(reader)
if err != nil {
fmt.Println("Error reading request:", err)
return
}
writer := &tcpResponseWriter{
conn: conn,
header: make(http.Header),
status: http.StatusOK,
}
if r.Host == utils.Getenv("domain") {
router.ServeHTTP(writer, r)
return
}
if utils.Getenv("tls_enabled") == "false" {
http.Redirect(writer, r, fmt.Sprintf("https://%s%s", r.Host, r.URL.RequestURI()), http.StatusFound)
return
}
slug := strings.Split(r.Host, ".")[0]
if slug == "" {
fmt.Println("Error parsing slug: ", r.Host)
return
}
sshSession, ok := session.Clients[slug]
if !ok {
fmt.Println("Error finding ssh session: ", slug)
return
}
rawRequest += fmt.Sprintf("%s %s %s\r\n", r.Method, r.URL.RequestURI(), r.Proto)
rawRequest += fmt.Sprintf("Host: %s\r\n", r.Host)
for k, v := range r.Header {
rawRequest += fmt.Sprintf("%s: %s\r\n", k, v[0])
}
rawRequest += "\r\n"
if r.Body != nil {
body, err := io.ReadAll(r.Body)
if err != nil {
log.Println("Error reading request body:", err)
} else {
rawRequest += string(body)
}
}
payload := []byte(rawRequest)
host, originPort := session.ParseAddr(conn.RemoteAddr().String())
sshSession.GetForwardedConnection(conn, host, sshSession.Connection, payload, originPort, 80, r.RequestURI, r.Method, r.Proto)
}