Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ build: scion-bat \
example-helloworld \
example-helloquic \
example-shttp-client example-shttp-server example-shttp-fileserver example-shttp-proxy \
example-shttp3-server \
example-sgrpc-server example-sgrpc-client

clean:
Expand Down Expand Up @@ -122,6 +123,10 @@ example-shttp-fileserver:
example-shttp-proxy:
cd _examples && go build -tags=$(TAGS) -o ../$(BIN)/$@ ./shttp/proxy

.PHONY: example-shttp3-server
example-shttp3-server:
cd _examples && go build -tags=$(TAGS) -o ../$(BIN)/$@ ./shttp3/server

.PHONY: example-sgrpc-server
example-sgrpc-server:
cd _examples && go build -tags=$(TAGS) -o ../$(BIN)/$@ ./sgrpc/server
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ The directory _examples contains examples for the usage of the SCION libraries.
Example for using gRPC over SCION/QUIC with the PAN library.
* [_examples/shttp](_examples/shttp/README.md):
Examples for using HTTP over SCION/QUIC, examples for servers, proxies, and clients.
* [_examples/shttp3](_examples/shttp3/README.md):
Example for using HTTP/3 over SCION/QUIC.

## bat

Expand Down
1 change: 1 addition & 0 deletions _examples/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ require (
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.53.0 // indirect
github.com/prometheus/procfs v0.14.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/scionproto/scion v0.12.1-0.20241223103250-0b42cbc42486 // indirect
github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect
Expand Down
2 changes: 2 additions & 0 deletions _examples/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+a
github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U=
github.com/prometheus/procfs v0.14.0 h1:Lw4VdGGoKEZilJsayHf0B+9YgLGREba2C6xr+Fdfq6s=
github.com/prometheus/procfs v0.14.0/go.mod h1:XL+Iwz8k8ZabyZfMFHPiilCniixqQarAy5Mu67pHlNQ=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
github.com/quic-go/quic-go v0.43.1 h1:fLiMNfQVe9q2JvSsiXo4fXOEguXHGGl9+6gLp4RPeZQ=
github.com/quic-go/quic-go v0.43.1/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
Expand Down
4 changes: 4 additions & 0 deletions _examples/shttp3/server/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Example for HTTP/3 over SCION/QUIC

## Simple server example
The server example `bin/example-shttp3-server` is analogous to the [shttp simple server example](../../shttp/README.md#simple-server-example), except that it always uses HTTPS and thus requires a certificate and key.
99 changes: 99 additions & 0 deletions _examples/shttp3/server/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// Copyright 2025 ETH Zurich
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
"encoding/json"
"flag"
"fmt"
"log"
"net/http"
"os"
"time"

"github.com/gorilla/handlers"
"github.com/netsec-ethz/scion-apps/pkg/shttp3"
)

func main() {
certFile := flag.String("cert", "", "Path to TLS server certificate for optional https")
keyFile := flag.String("key", "", "Path to TLS server key for optional https")
flag.Parse()

if *certFile == "" || *keyFile == "" {
flag.Usage()
os.Exit(2)
}

m := http.NewServeMux()

// handler that responds with a friendly greeting
m.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
// Status 200 OK will be set implicitly
w.Header().Set("Content-Type", "text/plain")
_, _ = w.Write([]byte(`Oh, hello!`))
})

// handler that responds with an image file
m.HandleFunc("/image", func(w http.ResponseWriter, r *http.Request) {
// serve the sample JPG file
// Status 200 OK will be set implicitly
// Content-Length will be inferred by server
// Content-Type will be detected by server
http.ServeFile(w, r, "dog.jpg")
})

// GET handler that responds with some json data
m.HandleFunc("/json", func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodGet {
data := struct {
Time string
Agent string
Proto string
Message string
}{
Time: time.Now().Format("2006.01.02 15:04:05"),
Agent: r.UserAgent(),
Proto: r.Proto,
Message: "success",
}
resp, _ := json.Marshal(data)
w.Header().Set("Content-Type", "application/json")
fmt.Fprint(w, string(resp))
} else {
http.Error(w, "wrong method: "+r.Method, http.StatusForbidden)
}
})

// POST handler that responds by parsing form values and returns them as string
m.HandleFunc("/form", func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodPost {
if err := r.ParseForm(); err != nil {
http.Error(w, "invalid form data", http.StatusBadRequest)
return
}
w.Header().Set("Content-Type", "text/plain")
fmt.Fprint(w, "received following data:\n")
for s := range r.PostForm {
fmt.Fprint(w, s, "=", r.PostFormValue(s), "\n")
}
} else {
http.Error(w, "wrong method: "+r.Method, http.StatusForbidden)
}
})

handler := handlers.LoggingHandler(os.Stdout, m)
log.Fatal(shttp3.ListenAndServe(":443", *certFile, *keyFile, handler))
}