1
0
Эх сурвалжийг харах

Added test case for transfer encoding

Toby Chui 9 сар өмнө
parent
commit
81af8f450e

+ 1 - 3
mod/dynamicproxy/loadbalance/loadbalance.go

@@ -47,12 +47,10 @@ type Upstream struct {
 
 // Create a new load balancer
 func NewLoadBalancer(options *Options) *RouteManager {
-	onlineStatusCheckerStopChan := make(chan bool)
-
 	return &RouteManager{
 		LoadBalanceMap:         sync.Map{},
 		OnlineStatusMap:        sync.Map{},
-		onlineStatusTickerStop: onlineStatusCheckerStopChan,
+		onlineStatusTickerStop: nil,
 		Options:                *options,
 	}
 }

+ 0 - 31
mod/dynamicproxy/loadbalance/onlineStatus.go

@@ -16,10 +16,6 @@ func (m *RouteManager) IsTargetOnline(matchingDomainOrIp string) bool {
 	return ok && isOnline
 }
 
-func (m *RouteManager) SetTargetOffline() {
-
-}
-
 // Ping a target to see if it is online
 func PingTarget(targetMatchingDomainOrIp string, requireTLS bool) bool {
 	client := &http.Client{
@@ -41,30 +37,3 @@ func PingTarget(targetMatchingDomainOrIp string, requireTLS bool) bool {
 
 	return resp.StatusCode >= 200 && resp.StatusCode <= 600
 }
-
-// StartHeartbeats start pinging each server every minutes to make sure all targets are online
-// Active mode only
-/*
-func (m *RouteManager) StartHeartbeats(pingTargets []*FallbackProxyTarget) {
-	ticker := time.NewTicker(1 * time.Minute)
-	defer ticker.Stop()
-
-	fmt.Println("Heartbeat started")
-	go func() {
-		for {
-			select {
-			case <-m.onlineStatusTickerStop:
-				ticker.Stop()
-				return
-			case <-ticker.C:
-				for _, target := range pingTargets {
-					go func(target *FallbackProxyTarget) {
-						isOnline := PingTarget(target.MatchingDomainOrIp, target.RequireTLS)
-						m.LoadBalanceMap.Store(target.MatchingDomainOrIp, isOnline)
-					}(target)
-				}
-			}
-		}
-	}()
-}
-*/

+ 73 - 0
tools/chunked-encoding-test/backend/backend.go

@@ -0,0 +1,73 @@
+package main
+
+import (
+	"fmt"
+	"io"
+	"log"
+	"net/http"
+	"time"
+)
+
+const (
+	backendResponse = "I am the backend"
+	backendStatus   = 404
+)
+
+func main() {
+	server := &http.Server{
+		Addr:    ":8088",
+		Handler: http.HandlerFunc(backendHandler),
+	}
+
+	// Run the server in a goroutine
+	log.Println("Starting server on :8088")
+	if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
+		log.Fatalf("Server failed to start: %v", err)
+	}
+}
+
+func HandlePost(w http.ResponseWriter, r *http.Request) {
+	// #1 add flusher
+	flusher, ok := w.(http.Flusher)
+	if !ok {
+		panic("expected http.ResponseWriter to be an http.Flusher")
+	}
+	w.Header().Set("Connection", "Keep-Alive")
+	w.Header().Set("Transfer-Encoding", "chunked")
+	w.Header().Set("X-Content-Type-Options", "nosniff")
+
+	ticker := time.NewTicker(time.Millisecond * 500)
+	go func() {
+		for t := range ticker.C {
+			// #2 add '\n'
+			io.WriteString(w, "Chunk\n")
+			fmt.Println("Tick at", t)
+			if flusher == nil {
+				break
+			}
+			flusher.Flush()
+		}
+	}()
+	time.Sleep(time.Second * 10)
+	ticker.Stop()
+}
+
+func backendHandler(w http.ResponseWriter, r *http.Request) {
+	if len(r.TransferEncoding) > 0 {
+		log.Printf("backend got TransferEncoding: %v", r.TransferEncoding)
+		HandlePost(w, r)
+		return
+	} else {
+		log.Println("No transfer encoding received")
+	}
+	if r.Header.Get("X-Forwarded-For") == "" {
+		log.Println("didn't get X-Forwarded-For header")
+	}
+	if g, e := r.Host, "ce.localhost"; g != e {
+		log.Printf("backend got Host header %q, want %q", g, e)
+	}
+	w.Header().Set("X-Foo", "bar")
+	http.SetCookie(w, &http.Cookie{Name: "flavor", Value: "chocolateChip"})
+	w.WriteHeader(backendStatus)
+	w.Write([]byte(backendResponse))
+}

+ 78 - 0
tools/chunked-encoding-test/chunked-encoding-passthrough_test.go

@@ -0,0 +1,78 @@
+package main_test
+
+/*
+	Reverse proxy chunked encoding test
+
+	To use this test file, set default site in your zoraxypointing to http://localhost:8088
+	 and then start the backend server and test script below.
+*/
+
+import (
+	"bytes"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"net/http"
+	"testing"
+)
+
+const (
+	backendResponse        = "I am the backend"
+	backendStatus          = 404
+	backendURL      string = "http://localhost"
+)
+
+func TestReverseProxy(t *testing.T) {
+	getReq, _ := http.NewRequest("GET", backendURL, nil)
+	getReq.Host = "localhost"
+	res, err := http.DefaultClient.Do(getReq)
+	if err != nil {
+		t.Fatalf("Get: %v", err)
+	}
+	if g, e := res.StatusCode, backendStatus; g != e {
+		t.Errorf("got res.StatusCode %d; expected %d", g, e)
+	}
+	if g, e := res.Header.Get("X-Foo"), "bar"; g != e {
+		t.Errorf("got X-Foo %q; expected %q", g, e)
+	}
+	if g, e := len(res.Header["Set-Cookie"]), 1; g != e {
+		t.Fatalf("got %d SetCookies, want %d", g, e)
+	}
+	if cookie := res.Cookies()[0]; cookie.Name != "flavor" {
+		t.Errorf("unexpected cookie %q", cookie.Name)
+	}
+	bodyBytes, _ := ioutil.ReadAll(res.Body)
+	if g, e := string(bodyBytes), backendResponse; g != e {
+		t.Errorf("got body %q; expected %q", g, e)
+	}
+}
+
+func TestChunkedTransfer(t *testing.T) {
+	// Test chunked encoding request
+	chunkedReq, _ := http.NewRequest("POST", backendURL, bytes.NewBufferString(""))
+	chunkedReq.Host = "localhost"
+	chunkedReq.TransferEncoding = []string{"chunked"}
+	chunkedRes, err := http.DefaultClient.Do(chunkedReq)
+	if err != nil {
+		t.Fatalf("Chunked POST: %v", err)
+	}
+	if g, e := chunkedRes.StatusCode, 200; g != e {
+		t.Errorf("got chunkedRes.StatusCode %d; expected %d", g, e)
+	}
+	// Read the response body in chunks and print to STDOUT
+	buf := make([]byte, 1024)
+	for {
+		n, err := chunkedRes.Body.Read(buf)
+		if n > 0 {
+			// Print the chunk to STDOUT
+			fmt.Print(string(buf[:n]))
+		}
+		if err != nil {
+			if err != io.EOF {
+				t.Fatalf("Error reading response body: %v", err)
+			}
+			break
+		}
+	}
+	chunkedRes.Body.Close()
+}

+ 2 - 0
tools/chunked-encoding-test/run-test-backend.bat

@@ -0,0 +1,2 @@
+cd backend
+go run backend.go

+ 45 - 26
web/components/rules.html

@@ -11,6 +11,17 @@
         border-radius: 0.6em;
         padding: 1em;
     }
+
+    .descheader{
+        display:none !important;
+    }
+
+    @media (min-width: 1367px) {
+        .descheader{
+            display:auto !important;
+
+        }
+    }
 </style>
 <div class="standardContainer">
     <div class="ui stackable grid">
@@ -47,16 +58,14 @@
                             </div>
                             <div class="content">
                                 <div class="field">
-                                    <label>Access Rule</label>
-                                    <div class="ui selection dropdown">
-                                        <input type="hidden" id="newProxyRuleAccessFilter" value="default">
-                                        <i class="dropdown icon"></i>
-                                        <div class="default text">Default</div>
-                                        <div class="menu" id="newProxyRuleAccessList">
-                                            <div class="item" data-value="default"><i class="ui yellow star icon"></i> Default</div>
-                                        </div>
+                                    <div class="ui checkbox">
+                                        <input type="checkbox" id="useStickySessionLB">
+                                        <label>Sticky Session<br><small>Enable stick session on upstream load balancing</small></label>
                                     </div>
-                                    <small>Allow regional access control using blacklist or whitelist. Use "default" for "allow all".</small>
+                                </div>
+                                <div class="ui horizontal divider">
+                                    <i class="ui green lock icon"></i>
+                                    Security
                                 </div>
                                 <div class="field">
                                     <div class="ui checkbox">
@@ -76,27 +85,21 @@
                                         <label>Allow plain HTTP access<br><small>Allow this subdomain to be connected without TLS (Require HTTP server enabled on port 80)</small></label>
                                     </div>
                                 </div>
-                                <div class="field">
-                                    <div class="ui checkbox">
-                                        <input type="checkbox" id="useStickySessionLB">
-                                        <label>Sticky Session<br><small>Enable stick session on upstream load balancing</small></label>
-                                    </div>
-                                </div>
-                                <div class="field">
-                                    <div class="ui checkbox">
-                                        <input type="checkbox" id="requireRateLimit">
-                                        <label>Require Rate Limit<br><small>This proxy endpoint will be rate limited.</small></label>
-                                    </div>
+                                <div class="ui horizontal divider">
+                                    <i class="ui red ban icon"></i>
+                                    Access Control
                                 </div>
                                 <div class="field">
-                                    <label>Rate Limit</label>
-                                    <div class="ui fluid right labeled input">
-                                        <input type="number" id="proxyRateLimit" placeholder="100" min="1" max="1000" value="100">
-                                        <div class="ui basic label">
-                                           req / sec / IP
+                                    <label>Access Rule</label>
+                                    <div class="ui selection dropdown">
+                                        <input type="hidden" id="newProxyRuleAccessFilter" value="default">
+                                        <i class="dropdown icon"></i>
+                                        <div class="default text">Default</div>
+                                        <div class="menu" id="newProxyRuleAccessList">
+                                            <div class="item" data-value="default"><i class="ui yellow star icon"></i> Default</div>
                                         </div>
                                     </div>
-                                    <small>Return a 429 error code if request rate exceed the rate limit.</small>
+                                    <small>Allow regional access control using blacklist or whitelist. Use "default" for "allow all".</small>
                                 </div>
                                 <div class="field">
                                     <div class="ui checkbox">
@@ -131,6 +134,22 @@
                                         </div>
                                     </div>
                                 </div>
+                                <div class="field">
+                                    <div class="ui checkbox">
+                                        <input type="checkbox" id="requireRateLimit">
+                                        <label>Require Rate Limit<br><small>This proxy endpoint will be rate limited.</small></label>
+                                    </div>
+                                </div>
+                                <div class="field">
+                                    <label>Rate Limit</label>
+                                    <div class="ui fluid right labeled input">
+                                        <input type="number" id="proxyRateLimit" placeholder="100" min="1" max="1000" value="100">
+                                        <div class="ui basic label">
+                                           req / sec / IP
+                                        </div>
+                                    </div>
+                                    <small>Return a 429 error code if request rate exceed the rate limit.</small>
+                                </div>
                             </div>
                         </div>
                     </div>