func SetDatabaseURI(uri string) { if RT.DB() == nil { RT.DatabaseURI = uri } else if uri != RT.DatabaseURI { rterr.Stop("Cannot rename database after connection to database has been initialized.") } }
/* Handles requests on the special explore port for methods of the explorer_api. TODO Really don't like that we have a separate, near duplicate handler function here for explorer_api serving. DRY violation!! */ func explorerHandler(w http.ResponseWriter, r *http.Request) { path := r.URL.Path pathSegments := strings.Split(path, "/") if len(pathSegments) > 0 && len(pathSegments[0]) == 0 { pathSegments = pathSegments[1:] } var queryString string // Last one or last one -1 has to have ? removed from it if len(pathSegments) > 0 { lastPiece := pathSegments[len(pathSegments)-1] i := strings.Index(lastPiece, "?") if i > -1 { queryString = lastPiece[i+1:] if i == 0 { pathSegments = pathSegments[:len(pathSegments)-1] } else { pathSegments[len(pathSegments)-1] = lastPiece[:i] } } else if len(lastPiece) == 0 { pathSegments = pathSegments[:len(pathSegments)-1] } } Logln(WEB_, pathSegments) Logln(WEB_, queryString) var handlerMethod *RMultiMethod pkgName := "shared.relish.pl2012/explorer_api/pkg/web" var pkg *RPackage pkg = RT.Packages[pkgName] if pkg == nil { rterr.Stop("No web package has been defined in shared.relish.pl2012/explorer_api") } // /foo/bar remainingPathSegments := pathSegments[:] for len(remainingPathSegments) > 0 { name := remainingPathSegments[0] methodName := underscoresToCamelCase(name) handlerMethod = findHandlerMethod(pkg, methodName) if handlerMethod != nil { Log(WEB_, "1. %s %s\n", pkg.Name, methodName) remainingPathSegments = remainingPathSegments[1:] Log(WEB_, " remainingPathSegments: %v\n", remainingPathSegments) break } pkgName += "/" + name Log(WEB_, "2. pkgName: %s\n", pkgName) nextPkg := RT.Packages[pkgName] if nextPkg != nil { remainingPathSegments = remainingPathSegments[1:] pkg = nextPkg continue } Logln(WEB_, " package was not found in RT.Packages") if strings.HasSuffix(pkgName, "/pkg/web/favicon.ico") { handlerMethod = findHandlerMethod(pkg, "icon") if handlerMethod != nil { Log(WEB_, "%s %s\n", pkg.Name, methodName) remainingPathSegments = remainingPathSegments[1:] break } else { http.Error(w, "", http.StatusNotFound) return } } // Note that default only handles paths that do not proceed down to // a subdirectory controller package. handlerMethod = findHandlerMethod(pkg, "default") if handlerMethod != nil { // remainingPathSegments = remainingPathSegments[1:] Log(WEB_, "3. Found default handler method in %s\n", pkg.Name) break } http.Error(w, "404 page or resource not found", http.StatusNotFound) return } if handlerMethod == nil { handlerMethod = findHandlerMethod(pkg, "index") } if handlerMethod == nil { http.Error(w, "404 page or resource not found", http.StatusNotFound) return } // RUN THE WEB DIALOG HANDLER METHOD Log(WEB_, "Running dialog handler method: %s\n", handlerMethod.Name) positionalArgStringValues := remainingPathSegments keywordArgStringValues, err := getKeywordArgs(r) if err != nil { fmt.Println(err) fmt.Fprintln(w, err) return } //var files map[string] []*multipart.FileHeader //if r.MultipartForm != nil { // files = r.MultipartForm.File // Could still be nil // } // TODO TODO Should return the InterpreterThread out of here, and // Do the commit or rollback later. // Or I should demand a thread from the interpreter separately, first, pass it in to // RunServiceMethod, then commit or rollback later. t := interpreter.NewThread(nil) defer interpreter.DeregisterThread(t) t.DBT().BeginTransaction("EXCLUSIVE") t.SetTransaction(NewTransaction()) t.SetErr("Uncaught panic while running explorer web app method.") defer t.SetTransaction(nil) defer t.CommitOrRollback() resultObjects, err := interpreter.RunServiceMethod(t, handlerMethod, positionalArgStringValues, keywordArgStringValues, r) if err != nil { fmt.Println(err) fmt.Fprintln(w, err) return } err = processResponse(w, r, pkg, handlerMethod.Name, resultObjects, t) if err != nil { fmt.Println(err) fmt.Fprintln(w, err) t.SetErr(err.Error()) return } t.SetErr("") // Yay! We did not panic }
func handler(w http.ResponseWriter, r *http.Request) { path := r.URL.Path possibleDotPos := len(path) - 7 if possibleDotPos < 0 { possibleDotPos = 0 } if (!strings.HasSuffix(path, ".ico")) && (strings.LastIndex(path, ".") > possibleDotPos) && (!strings.Contains(path, "?")) { // Serve static content // fmt.Fprintln(w, r.URL.Path) filePath := webPackageSrcDirPath + "/static" + path http.ServeFile(w, r, filePath) return } pathSegments := strings.Split(path, "/") if len(pathSegments) > 0 && len(pathSegments[0]) == 0 { pathSegments = pathSegments[1:] } var queryString string // Last one or last one -1 has to have ? removed from it if len(pathSegments) > 0 { lastPiece := pathSegments[len(pathSegments)-1] i := strings.Index(lastPiece, "?") if i > -1 { queryString = lastPiece[i+1:] if i == 0 { pathSegments = pathSegments[:len(pathSegments)-1] } else { pathSegments[len(pathSegments)-1] = lastPiece[:i] } } else if len(lastPiece) == 0 { pathSegments = pathSegments[:len(pathSegments)-1] } } Logln(WEB_, pathSegments) Logln(WEB_, queryString) var handlerMethod *RMultiMethod pkgName := RT.RunningArtifact + "/pkg/web" var pkg *RPackage pkg = RT.Packages[pkgName] if pkg == nil { rterr.Stop("No web package has been defined in " + RT.RunningArtifact) } // /foo/bar remainingPathSegments := pathSegments[:] for len(remainingPathSegments) > 0 { name := remainingPathSegments[0] methodName := underscoresToCamelCase(name) handlerMethod = findHandlerMethod(pkg, methodName) if handlerMethod != nil { Log(WEB_, "1. %s %s\n", pkg.Name, methodName) remainingPathSegments = remainingPathSegments[1:] Log(WEB_, " remainingPathSegments: %v\n", remainingPathSegments) break } pkgName += "/" + name Log(WEB_, "2. pkgName: %s\n", pkgName) nextPkg := RT.Packages[pkgName] if nextPkg != nil { remainingPathSegments = remainingPathSegments[1:] pkg = nextPkg continue } Logln(WEB_, " package was not found in RT.Packages") if strings.HasSuffix(pkgName, "/pkg/web/favicon.ico") { handlerMethod = findHandlerMethod(pkg, "icon") if handlerMethod != nil { Log(WEB_, "%s %s\n", pkg.Name, methodName) remainingPathSegments = remainingPathSegments[1:] break } else { http.Error(w, "", http.StatusNotFound) return } } // Note that default only handles paths that do not proceed down to // a subdirectory controller package. handlerMethod = findHandlerMethod(pkg, "default") if handlerMethod != nil { // remainingPathSegments = remainingPathSegments[1:] Log(WEB_, "3. Found default handler method in %s\n", pkg.Name) break } http.Error(w, "404 page or resource not found", http.StatusNotFound) return } if handlerMethod == nil { handlerMethod = findHandlerMethod(pkg, "index") } if handlerMethod == nil { http.Error(w, "404 page or resource not found", http.StatusNotFound) return } // RUN THE WEB DIALOG HANDLER METHOD Log(WEB_, "Running dialog handler method: %s\n", handlerMethod.Name) positionalArgStringValues := remainingPathSegments keywordArgStringValues, err := getKeywordArgs(r) if err != nil { fmt.Println(err) fmt.Fprintln(w, err) return } //var files map[string] []*multipart.FileHeader //if r.MultipartForm != nil { // files = r.MultipartForm.File // Could still be nil // } // TODO TODO Should return the InterpreterThread out of here, and // Do the commit or rollback later. // Or I should demand a thread from the interpreter separately, first, pass it in to // RunServiceMethod, then commit or rollback later. t := interpreter.NewThread(nil) defer interpreter.DeregisterThread(t) Log(GC2_, "Running dialog handler method: %s\n", handlerMethod.Name) Log(GC2_, " Args: %v\n", positionalArgStringValues) Log(GC2_, " KW Args: %v\n", keywordArgStringValues) // Get annotations of the URL-mapped method. // These determine what kind of transaction behaviour it will have. // Options: // <none> Wrap method execution and response processing in an IMMEDIATE (reserved for write) TRANSACTION // "READ" Wrap method execution and response processing in a DEFERRED TRANSACTION which has done a trial db read. // "NOTX" Do not use a long transaction at all. Use AUTOCOMMIT transactions, one per db statement. // If not doing any persistence in the service method, use NOTX // mods, err := interpreter.GetServiceMethodModifiers(handlerMethod) if err != nil { panic(err) } if !mods["NOTX"] { var transactionType string if mods["READ"] { transactionType = "DEFERRED" } else { transactionType = "EXCLUSIVE" } err := t.DBT().BeginTransaction(transactionType) if err != nil { fmt.Println(err) fmt.Fprintln(w, err) t.SetErr(err.Error()) return } t.SetTransaction(NewTransaction()) defer t.SetTransaction(nil) defer t.CommitOrRollback() } t.SetErr("Uncaught panic while running web app method.") // fmt.Printf("Began transaction now running dialog handler method: %s\n",handlerMethod.Name) resultObjects, err := interpreter.RunServiceMethod(t, handlerMethod, positionalArgStringValues, keywordArgStringValues, r) // fmt.Printf("Finished running dialog handler method: %s\n",handlerMethod.Name) Log(GC2_, "Finished running dialog handler method: %s\n", handlerMethod.Name) Log(GC2_, " Args: %v\n", positionalArgStringValues) Log(GC2_, " KW Args: %v\n", keywordArgStringValues) if err != nil { fmt.Println(err) fmt.Fprintln(w, err) t.SetErr(err.Error()) return } err = processResponse(w, r, pkg, handlerMethod.Name, resultObjects, t) if err != nil { fmt.Println(err) fmt.Fprintln(w, err) t.SetErr(err.Error()) return } t.SetErr("") // Yay! We did not panic // fmt.Println("finished processing response of " + handlerMethod.Name) }