github.com/pion/webrtc/v4@v4.0.1/examples/examples.go (about)

     1  // SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
     2  // SPDX-License-Identifier: MIT
     3  
     4  // HTTP server that demonstrates Pion WebRTC examples
     5  package main
     6  
     7  import (
     8  	"encoding/json"
     9  	"flag"
    10  	"go/build"
    11  	"html/template"
    12  	"log"
    13  	"net/http"
    14  	"os"
    15  	"path/filepath"
    16  	"strings"
    17  )
    18  
    19  // Examples represents the examples loaded from examples.json.
    20  type Examples []*Example
    21  
    22  // Example represents an example loaded from examples.json.
    23  type Example struct {
    24  	Title       string `json:"title"`
    25  	Link        string `json:"link"`
    26  	Description string `json:"description"`
    27  	Type        string `json:"type"`
    28  	IsJS        bool
    29  	IsWASM      bool
    30  }
    31  
    32  func main() {
    33  	addr := flag.String("address", ":80", "Address to host the HTTP server on.")
    34  	flag.Parse()
    35  
    36  	log.Println("Listening on", *addr)
    37  	err := serve(*addr)
    38  	if err != nil {
    39  		log.Fatalf("Failed to serve: %v", err)
    40  	}
    41  }
    42  
    43  func serve(addr string) error {
    44  	// Load the examples
    45  	examples := getExamples()
    46  
    47  	// Load the templates
    48  	homeTemplate := template.Must(template.ParseFiles("index.html"))
    49  
    50  	// Serve the required pages
    51  	// DIY 'mux' to avoid additional dependencies
    52  	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    53  		url := r.URL.Path
    54  		if url == "/wasm_exec.js" {
    55  			http.FileServer(http.Dir(filepath.Join(build.Default.GOROOT, "misc/wasm/"))).ServeHTTP(w, r)
    56  			return
    57  		}
    58  
    59  		// Split up the URL. Expected parts:
    60  		// 1: Base url
    61  		// 2: "example"
    62  		// 3: Example type: js or wasm
    63  		// 4: Example folder, e.g.: data-channels
    64  		// 5: Static file as part of the example
    65  		parts := strings.Split(url, "/")
    66  		if len(parts) > 4 &&
    67  			parts[1] == "example" {
    68  			exampleType := parts[2]
    69  			exampleLink := parts[3]
    70  			for _, example := range *examples {
    71  				if example.Link != exampleLink {
    72  					continue
    73  				}
    74  				fiddle := filepath.Join(exampleLink, "jsfiddle")
    75  				if len(parts[4]) != 0 {
    76  					http.StripPrefix("/example/"+exampleType+"/"+exampleLink+"/", http.FileServer(http.Dir(fiddle))).ServeHTTP(w, r)
    77  					return
    78  				}
    79  
    80  				temp := template.Must(template.ParseFiles("example.html"))
    81  				_, err := temp.ParseFiles(filepath.Join(fiddle, "demo.html"))
    82  				if err != nil {
    83  					panic(err)
    84  				}
    85  
    86  				data := struct {
    87  					*Example
    88  					JS bool
    89  				}{
    90  					example,
    91  					exampleType == "js",
    92  				}
    93  
    94  				err = temp.Execute(w, data)
    95  				if err != nil {
    96  					panic(err)
    97  				}
    98  				return
    99  			}
   100  		}
   101  
   102  		// Serve the main page
   103  		err := homeTemplate.Execute(w, examples)
   104  		if err != nil {
   105  			panic(err)
   106  		}
   107  	})
   108  
   109  	// Start the server
   110  	// nolint: gosec
   111  	return http.ListenAndServe(addr, nil)
   112  }
   113  
   114  // getExamples loads the examples from the examples.json file.
   115  func getExamples() *Examples {
   116  	file, err := os.Open("./examples.json")
   117  	if err != nil {
   118  		panic(err)
   119  	}
   120  	defer func() {
   121  		closeErr := file.Close()
   122  		if closeErr != nil {
   123  			panic(closeErr)
   124  		}
   125  	}()
   126  
   127  	var examples Examples
   128  	err = json.NewDecoder(file).Decode(&examples)
   129  	if err != nil {
   130  		panic(err)
   131  	}
   132  
   133  	for _, example := range examples {
   134  		fiddle := filepath.Join(example.Link, "jsfiddle")
   135  		js := filepath.Join(fiddle, "demo.js")
   136  		if _, err := os.Stat(js); !os.IsNotExist(err) {
   137  			example.IsJS = true
   138  		}
   139  		wasm := filepath.Join(fiddle, "demo.wasm")
   140  		if _, err := os.Stat(wasm); !os.IsNotExist(err) {
   141  			example.IsWASM = true
   142  		}
   143  	}
   144  
   145  	return &examples
   146  }