Forráskód Böngészése

Improve curl streaming

ajasibley 5 hónapja
szülő
commit
e6d63c91a4
2 módosított fájl, 34 hozzáadás és 4 törlés
  1. 4 3
      README.md
  2. 30 1
      http.go

+ 4 - 3
README.md

@@ -9,7 +9,8 @@ A lightweight language model chat service accessible through HTTP, SSH, DNS, and
 open https://ch.at
 
 # Terminal
-curl ch.at/?q=hello             # Query parameter (handles special chars)
+curl ch.at/?q=hello             # Streams response with curl's default buffering
+curl -N ch.at/?q=hello          # Streams response without buffering (smoother)
 curl ch.at/what-is-rust         # Path-based (cleaner URLs, hyphens become spaces)
 ssh ch.at
 
@@ -22,7 +23,7 @@ curl ch.at/v1/chat/completions
 
 ## Design
 
-- ~1,200 lines of Go, three dependencies
+- ~1,300 lines of Go, three direct dependencies
 - Single static binary
 - No accounts, no logs, no tracking
 - Configuration through source code (edit and recompile)
@@ -147,7 +148,7 @@ Edit constants in source files:
 ## Limitations
 
 - **DNS**: Responses limited to ~500 bytes. Complex queries may time out after 4s. DNS queries automatically request concise, plain-text responses
-- **History**: Limited to 2KB in web interface to prevent URL overflow
+- **History**: Limited to 64KB to ensure compatibility across systems
 - **Rate limiting**: Basic IP-based limiting to prevent abuse
 - **No encryption**: SSH is encrypted, but HTTP/DNS are not
 

+ 30 - 1
http.go

@@ -149,6 +149,36 @@ func handleRoot(w http.ResponseWriter, r *http.Request) {
 			return
 		}
 
+		// Plain text streaming for curl
+		userAgent := r.Header.Get("User-Agent")
+		isCurl := strings.Contains(userAgent, "curl") && !wantsHTML && !wantsJSON && !wantsStream
+		if isCurl {
+			w.Header().Set("Content-Type", "text/plain; charset=utf-8")
+			w.Header().Set("Transfer-Encoding", "chunked")
+			w.Header().Set("X-Accel-Buffering", "no")
+			flusher := w.(http.Flusher)
+
+			fmt.Fprintf(w, "Q: %s\nA: ", query)
+			flusher.Flush()
+
+			ch := make(chan string)
+			go func() {
+				if _, err := LLM(prompt, ch); err != nil {
+					ch <- err.Error()
+					close(ch)
+				}
+			}()
+
+			response := ""
+			for chunk := range ch {
+				fmt.Fprint(w, chunk)
+				response += chunk
+				flusher.Flush()
+			}
+			fmt.Fprint(w, "\n")
+			return
+		}
+
 		response, err := LLM(prompt, nil)
 		if err != nil {
 			content = err.Error()
@@ -333,4 +363,3 @@ func handleChatCompletions(w http.ResponseWriter, r *http.Request) {
 		json.NewEncoder(w).Encode(chatResp)
 	}
 }
-