github.com/hzck/speedroute@v0.0.0-20201115191102-403b7d0e443f/main_old.txt (about)

     1  // Package main creates the web server.
     2  package main
     3  
     4  import (
     5  	"encoding/json"
     6  	"io/ioutil"
     7  	"log"
     8  	"net/http"
     9  	"os"
    10  	"strings"
    11  	"sync"
    12  	"time"
    13  
    14  	"github.com/gorilla/mux"
    15  
    16  	a "github.com/hzck/speedroute/algorithm"
    17  	p "github.com/hzck/speedroute/parser"
    18  )
    19  
    20  var mutex = &sync.Mutex{}
    21  
    22  type iIOUtil interface {
    23  	ReadDir(dirname string) ([]string, error)
    24  }
    25  
    26  type iFileSystem interface {
    27  	Create(name string) (iFile, error)
    28  	IsNotExist(err error) bool
    29  	Remove(name string) error
    30  	Stat(name string) (os.FileInfo, error)
    31  }
    32  
    33  type iFile interface {
    34  	Close() error
    35  	WriteString(s string) (int, error)
    36  }
    37  
    38  type iFileInfo interface {
    39  	Name() string
    40  }
    41  
    42  type ioutilFS struct{}
    43  
    44  func (ioutilFS) ReadDir(dirname string) ([]string, error) {
    45  	readDir, err := ioutil.ReadDir(dirname)
    46  	if err != nil {
    47  		return nil, err
    48  	}
    49  	fileInfos := make([]iFileInfo, len(readDir))
    50  	for i, v := range readDir {
    51  		fileInfos[i] = v
    52  	}
    53  	return extractNames(fileInfos), nil
    54  }
    55  
    56  func extractNames(readDir []iFileInfo) []string {
    57  	list := make([]string, len(readDir))
    58  	for i := range list {
    59  		file := readDir[i].Name()
    60  		list[i] = file[0 : len(file)-5]
    61  	}
    62  	return list
    63  }
    64  
    65  type osFile struct {
    66  	file *os.File
    67  }
    68  
    69  func (ref *osFile) WriteString(s string) (int, error) {
    70  	return ref.file.WriteString(s)
    71  }
    72  
    73  func (ref *osFile) Close() error {
    74  	return ref.file.Close()
    75  }
    76  
    77  type osFS struct{}
    78  
    79  func (osFS) Create(name string) (iFile, error) {
    80  	f, err := os.Create(name)
    81  	if err != nil {
    82  		return nil, err
    83  	}
    84  	return &osFile{f}, nil
    85  }
    86  
    87  func (osFS) IsNotExist(err error) bool {
    88  	return os.IsNotExist(err)
    89  }
    90  
    91  func (osFS) Remove(name string) error {
    92  	return os.Remove(name)
    93  }
    94  
    95  func (osFS) Stat(name string) (os.FileInfo, error) {
    96  	return os.Stat(name)
    97  }
    98  
    99  func main2() {
   100  	// Creating logfile
   101  	f, err := os.OpenFile("logfile", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
   102  	if err != nil {
   103  		panic(err)
   104  	}
   105  	defer func() {
   106  		if closeErr := f.Close(); closeErr != nil && err == nil {
   107  			panic(closeErr)
   108  		}
   109  	}()
   110  	log.SetOutput(f)
   111  
   112  	log.Println("### Server started ###")
   113  	fs := osFS{}
   114  	io := ioutilFS{}
   115  	r := mux.NewRouter()
   116  	r.HandleFunc("/create/{id:[A-Za-z0-9-_]+}/{pw:.*}", createGraphHandler(fs)).Methods("POST")
   117  	r.HandleFunc("/graphs", listGraphsHandler(io)).Methods("GET")
   118  	r.HandleFunc("/graph/{id:[A-Za-z0-9-_]+}", getGraphHandler(fs)).Methods("GET")
   119  	r.HandleFunc("/graph/{id:[A-Za-z0-9-_]+}/{pw:.*}", saveGraphHandler(fs)).Methods("POST")
   120  	r.PathPrefix("/").Handler(http.FileServer(http.Dir("public")))
   121  
   122  	log.Println(http.ListenAndServe(":8001", r))
   123  }
   124  
   125  func createFile(fs iFileSystem, filename, fileContent string) (httpStatus int, err error) {
   126  	file, err := fs.Create(filename)
   127  	if err != nil {
   128  		log.Println(err)
   129  		return http.StatusInternalServerError, err
   130  	}
   131  	defer func() {
   132  		if closeErr := file.Close(); closeErr != nil && err == nil {
   133  			log.Println(closeErr)
   134  			httpStatus = http.StatusInternalServerError
   135  			err = closeErr
   136  			return
   137  		}
   138  	}()
   139  	_, err = file.WriteString(fileContent)
   140  	if err != nil {
   141  		log.Println(err)
   142  		removeErr := fs.Remove(filename)
   143  		if removeErr != nil {
   144  			log.Println(removeErr)
   145  		}
   146  		return http.StatusInternalServerError, err
   147  	}
   148  	return http.StatusCreated, nil
   149  }
   150  
   151  func createGraphHandler(fs iFileSystem) http.HandlerFunc {
   152  	return func(w http.ResponseWriter, r *http.Request) {
   153  		filename := "graphs/" + mux.Vars(r)["id"] + ".json"
   154  		if _, err := fs.Stat(filename); fs.IsNotExist(err) {
   155  			fileContent := "{}"
   156  			newGraph, err := ioutil.ReadAll(r.Body)
   157  			if err != nil {
   158  				log.Println(err)
   159  				w.WriteHeader(http.StatusInternalServerError)
   160  				return
   161  			}
   162  			if len(newGraph) > 0 {
   163  				fileContent, err = p.LivesplitXMLtoJSON(string(newGraph))
   164  				if err != nil {
   165  					w.WriteHeader(http.StatusBadRequest)
   166  					return
   167  				}
   168  			}
   169  			httpStatus, err := createFile(fs, filename, fileContent)
   170  			if err == nil {
   171  				pwFilename := "passwords/" + mux.Vars(r)["id"] + ".txt"
   172  				httpStatus, err = createFile(fs, pwFilename, mux.Vars(r)["pw"])
   173  				if err != nil {
   174  					removeErr := fs.Remove(filename)
   175  					if removeErr != nil {
   176  						log.Println(removeErr)
   177  					}
   178  				}
   179  			}
   180  			w.WriteHeader(httpStatus)
   181  			return
   182  		}
   183  		w.WriteHeader(http.StatusConflict)
   184  	}
   185  }
   186  
   187  func getGraphHandler(fs iFileSystem) http.HandlerFunc {
   188  	return func(w http.ResponseWriter, r *http.Request) {
   189  		filename := "graphs/" + mux.Vars(r)["id"] + ".json"
   190  		if _, err := fs.Stat(filename); fs.IsNotExist(err) {
   191  			log.Println(err)
   192  			w.WriteHeader(http.StatusNotFound)
   193  			return
   194  		}
   195  		content, err := ioutil.ReadFile(filename)
   196  		if err != nil {
   197  			log.Println(err)
   198  			w.WriteHeader(http.StatusInternalServerError)
   199  			return
   200  		}
   201  		w.Header().Set("Content-Type", "application/json")
   202  		_, err = w.Write(content)
   203  		if err != nil {
   204  			log.Println(err)
   205  			w.WriteHeader(http.StatusInternalServerError)
   206  		}
   207  	}
   208  }
   209  
   210  func saveGraphHandler(fs iFileSystem) http.HandlerFunc {
   211  	return func(w http.ResponseWriter, r *http.Request) {
   212  		filename := "graphs/" + mux.Vars(r)["id"] + ".json"
   213  		if _, err := fs.Stat(filename); fs.IsNotExist(err) {
   214  			w.WriteHeader(http.StatusNotFound)
   215  			return
   216  		}
   217  		pwFilename := "passwords/" + mux.Vars(r)["id"] + ".txt"
   218  		if _, err := fs.Stat(pwFilename); fs.IsNotExist(err) {
   219  			w.WriteHeader(http.StatusNotFound)
   220  			return
   221  		}
   222  		pw, _ := ioutil.ReadFile(pwFilename)
   223  		if strings.Compare(string(pw), mux.Vars(r)["pw"]) != 0 {
   224  			w.WriteHeader(http.StatusUnauthorized)
   225  			return
   226  		}
   227  		newGraph, err := ioutil.ReadAll(r.Body)
   228  		if err != nil {
   229  			log.Println(err)
   230  			w.WriteHeader(http.StatusInternalServerError)
   231  			return
   232  		}
   233  		err = ioutil.WriteFile(filename, newGraph, 0600)
   234  		if err != nil {
   235  			log.Println(err)
   236  			w.WriteHeader(http.StatusInternalServerError)
   237  			return
   238  		}
   239  
   240  		graph, err := p.CreateGraphFromFile(filename)
   241  		if err != nil {
   242  			log.Println(err)
   243  			w.WriteHeader(http.StatusInternalServerError)
   244  			return
   245  		}
   246  
   247  		// Potential bottleneck draining memory, making sure only one graph is routed at any moment.
   248  		// Should add timing in log if it takes > 1s? 10s?
   249  		mutex.Lock()
   250  		start := time.Now()
   251  		result := a.Route(graph)
   252  		log.Printf("%s taking %s\n", filename, time.Since(start))
   253  		mutex.Unlock()
   254  		js, err := p.CreateJSONFromRoutedPath(result)
   255  		w.Header().Set("Content-Type", "application/json")
   256  		if err != nil {
   257  			log.Println(err)
   258  			w.WriteHeader(http.StatusInternalServerError)
   259  			return
   260  		}
   261  		_, err = w.Write(js)
   262  		if err != nil {
   263  			log.Println(err)
   264  			w.WriteHeader(http.StatusInternalServerError)
   265  			return
   266  		}
   267  	}
   268  }
   269  
   270  func listGraphsHandler(io iIOUtil) http.HandlerFunc {
   271  	return func(w http.ResponseWriter, r *http.Request) {
   272  		graphs, err := io.ReadDir("graphs")
   273  		if err != nil {
   274  			log.Println(err)
   275  			w.WriteHeader(http.StatusInternalServerError)
   276  			return
   277  		}
   278  		js, err := json.Marshal(graphs)
   279  		if err != nil {
   280  			log.Println(err)
   281  			w.WriteHeader(http.StatusInternalServerError)
   282  			return
   283  		}
   284  		w.Header().Set("Content-Type", "application/json")
   285  		_, err = w.Write(js)
   286  		if err != nil {
   287  			log.Println(err)
   288  			w.WriteHeader(http.StatusInternalServerError)
   289  			return
   290  		}
   291  	}
   292  }