Skip to content

Commit

Permalink
Code Cleanup & Refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
joelsmith-2019 committed Jan 12, 2024
1 parent f79d41a commit 564f041
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 184 deletions.
3 changes: 1 addition & 2 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -595,8 +595,7 @@ func (app *App) RegisterAPIRoutes(apiSvr *api.Server, _ config.APIConfig) {
// register app's OpenAPI routes.
apiSvr.Router.Handle("/static/openapi.yml", http.FileServer(http.FS(docs.Docs)))
apiSvr.Router.HandleFunc("/", openapiconsole.Handler(Name, "/static/openapi.yml"))
apiSvr.Router.HandleFunc("/webhost", webhost.Handler())
apiSvr.Router.HandleFunc("/fs/{contract}/{name}/{path:.*}", webhost.Handler2())
apiSvr.Router.HandleFunc("/webhost/{contract}/{name}/{path:.*}", webhost.Handler())
}

// RegisterTxService implements the Application.RegisterTxService method.
Expand Down
2 changes: 1 addition & 1 deletion app/webhost/_scripts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@ sleep 3

junod q wasm contract-state smart $ADDRESS '{"get_website":{"name":"test"}}' --home=/home/joel/.juno1

# Website should be available at: http://localhost:1317/fs/juno14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9skjuwg8/test/
# Website should be available at: http://localhost:1317/webhost/juno14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9skjuwg8/test/
150 changes: 117 additions & 33 deletions app/webhost/console.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
package webhost

import (
"archive/zip"
"bytes"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"strings"
)

// TODO:
// https://github.com/rogchap/v8go ?
// Allow ZIP file upload into the contract? (easier to use images, else you need to use IPFS or direct links off chain)

const (
address = ":8787"
restServer = "http://0.0.0.0:1317/cosmwasm/wasm/v1/contract/"
Expand All @@ -28,53 +25,140 @@ type Website struct {

func Handler() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
params := r.URL.Query()

Check failure on line 28 in app/webhost/console.go

View workflow job for this annotation

GitHub Actions / lint

File is not `gofumpt`-ed (gofumpt)
if len(params["contract"]) == 0 || len(params["name"]) == 0 {
w.WriteHeader(http.StatusBadRequest)
if _, err := w.Write([]byte("contract and name are required")); err != nil {
fmt.Println("error writing response: ", err)
}
return
}
// Get request route
route := strings.Split(r.URL.Path, "/")[2:]

contract := params["contract"][0]
name := params["name"][0]
// Pull out contract & name from route
contract := route[0]
name := route[1]

b64Query := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf(`{"get_website":{"name":"%s"}}`, name)))
// Determine file path, default to index.html if none specified
path := strings.Join(route[2:], "/")
if path == "" {
path = "index.html"
}

res, err := http.Get(restServer + contract + "/smart/" + b64Query)
// Send request to CosmWasm contract, retrieve website
website, err := makeRequest(contract, name, path)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
writeResponse(w, "error creating request: "+err.Error())
writeResponse(w, "error making request: "+err.Error())
return
}
defer res.Body.Close()

resBody, err := io.ReadAll(res.Body)
// Decode & unzip website source files
zr, err := decodeAndUnzip(website.Data.Source)
if err != nil {
fmt.Printf("client: could not read response body: %s\n", err)
os.Exit(1)
w.WriteHeader(http.StatusInternalServerError)
writeResponse(w, "error decoding and unzipping file: "+err.Error())
return
}

if len(resBody) > 0 && strings.Contains(string(resBody), "data") {
var website Website
err = json.Unmarshal(resBody, &website)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
writeResponse(w, "error unmarshalling response body: "+err.Error())
return
// Find file in zip at path
for _, f := range zr.File {
if f.Name == path {
rc, err := f.Open()
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
writeResponse(w, "error opening file: "+err.Error())
return
}
defer rc.Close()

// Read file into buffer
buf := new(bytes.Buffer)
if _, err := io.Copy(buf, rc); err != nil {

Check failure on line 71 in app/webhost/console.go

View workflow job for this annotation

GitHub Actions / lint

G110: Potential DoS vulnerability via decompression bomb (gosec)
w.WriteHeader(http.StatusInternalServerError)
writeResponse(w, "error reading file: "+err.Error())
return
}

// Set content type
setContentType(w, path)

// Write buffer to response
if _, err := w.Write(buf.Bytes()); err != nil {
w.WriteHeader(http.StatusInternalServerError)
writeResponse(w, "error writing response: "+err.Error())
}

break
}
}
}
}

writeResponse(w, website.Data.Source)
return
// Make request to contract through CosmWasm REST server
func makeRequest(contract, name, path string) (Website, error) {

Check warning on line 93 in app/webhost/console.go

View workflow job for this annotation

GitHub Actions / lint

unused-parameter: parameter 'path' seems to be unused, consider removing or renaming it as _ (revive)
var website Website

b64Query := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf(`{"get_website":{"name":"%s"}}`, name)))
url := restServer + contract + "/smart/" + b64Query

res, err := http.Get(url)

Check failure on line 99 in app/webhost/console.go

View workflow job for this annotation

GitHub Actions / lint

G107: Potential HTTP request made with variable url (gosec)
if err != nil {
return website, err
}
defer res.Body.Close()

resBody, err := io.ReadAll(res.Body)
if err != nil {
return website, err
}

if len(resBody) > 0 && strings.Contains(string(resBody), "data") {
if err = json.Unmarshal(resBody, &website); err != nil {
return website, err
}
}

return website, nil
}

// Decode from base 64 and unzip file, return zip reader
func decodeAndUnzip(source string) (*zip.Reader, error) {
// Decode from base 64
decodedBytes, err := base64.StdEncoding.DecodeString(source)
if err != nil {
return nil, err
}

// Unzip
reader := bytes.NewReader(decodedBytes)
zr, err := zip.NewReader(reader, int64(len(decodedBytes)))
if err != nil {
return nil, err
}

return zr, nil
}

w.WriteHeader(http.StatusNotFound)
writeResponse(w, "no website found")
// Set the content type of the response based on the file's extension
func setContentType(w http.ResponseWriter, filePath string) {
// Set content type
if strings.HasSuffix(filePath, ".html") {

Check failure on line 140 in app/webhost/console.go

View workflow job for this annotation

GitHub Actions / lint

ifElseChain: rewrite if-else to switch statement (gocritic)
w.Header().Set("Content-Type", "text/html")
} else if strings.HasSuffix(filePath, ".css") {
w.Header().Set("Content-Type", "text/css")
} else if strings.HasSuffix(filePath, ".js") {
w.Header().Set("Content-Type", "text/javascript")
} else if strings.HasSuffix(filePath, ".png") {
w.Header().Set("Content-Type", "image/png")
} else if strings.HasSuffix(filePath, ".jpg") || strings.HasSuffix(filePath, ".jpeg") {
w.Header().Set("Content-Type", "image/jpeg")
} else if strings.HasSuffix(filePath, ".gif") {
w.Header().Set("Content-Type", "image/gif")
} else if strings.HasSuffix(filePath, ".svg") {
w.Header().Set("Content-Type", "image/svg+xml")
} else if strings.HasSuffix(filePath, ".ico") {
w.Header().Set("Content-Type", "image/x-icon")
} else {
w.Header().Set("Content-Type", "text/plain")
}
}

// Helper function for writing response
func writeResponse(w http.ResponseWriter, resBody string) {
if _, err := w.Write([]byte(resBody)); err != nil {
fmt.Println("error writing response: ", err)
Expand Down
148 changes: 0 additions & 148 deletions app/webhost/file_server.go

This file was deleted.

0 comments on commit 564f041

Please sign in to comment.