| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- // Package p contains an HTTP Cloud Function.
- package p
- import (
- "encoding/json"
- "fmt"
- "io"
- "log"
- "net/http"
- "cloud.google.com/go/bigtable"
- )
- // fetch rows by matching payload value
- func FindValues(w http.ResponseWriter, r *http.Request) {
- // Set CORS headers for the preflight request
- if r.Method == http.MethodOptions {
- w.Header().Set("Access-Control-Allow-Origin", "*")
- w.Header().Set("Access-Control-Allow-Methods", "POST")
- w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
- w.Header().Set("Access-Control-Max-Age", "3600")
- w.WriteHeader(http.StatusNoContent)
- return
- }
- // Set CORS headers for the main request.
- w.Header().Set("Access-Control-Allow-Origin", "*")
- var columnFamily, columnName, value, emitterChain, emitterAddress string
- // allow GET requests with querystring params, or POST requests with json body.
- switch r.Method {
- case http.MethodGet:
- queryParams := r.URL.Query()
- columnFamily = queryParams.Get("columnFamily")
- columnName = queryParams.Get("columnName")
- value = queryParams.Get("value")
- emitterChain = queryParams.Get("emitterChain")
- emitterAddress = queryParams.Get("emitterAddress")
- // check for empty values
- if columnFamily == "" || columnName == "" || value == "" {
- fmt.Fprint(w, "query params ['columnFamily', 'columnName', 'value'] cannot be empty")
- http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
- return
- }
- case http.MethodPost:
- // declare request body properties
- var d struct {
- ColumnFamily string `json:"columnFamily"`
- ColumnName string `json:"columnName"`
- Value string `json:"value"`
- EmitterChain string `json:"emitterChain"`
- EmitterAddress string `json:"emitterAddress"`
- }
- // deserialize request body
- if err := json.NewDecoder(r.Body).Decode(&d); err != nil {
- switch err {
- case io.EOF:
- fmt.Fprint(w, "request body required")
- return
- default:
- log.Printf("json.NewDecoder: %v", err)
- http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
- return
- }
- }
- // check for empty values
- if d.ColumnFamily == "" || d.ColumnName == "" || d.Value == "" {
- fmt.Fprint(w, "body values ['columnFamily', 'columnName', 'value'] cannot be empty")
- http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
- return
- }
- columnFamily = d.ColumnFamily
- columnName = d.ColumnName
- value = d.Value
- emitterChain = d.EmitterChain
- emitterAddress = d.EmitterAddress
- default:
- http.Error(w, "405 - Method Not Allowed", http.StatusMethodNotAllowed)
- log.Println("Method Not Allowed")
- return
- }
- if columnFamily != "TokenTransferPayload" &&
- columnFamily != "AssetMetaPayload" &&
- columnFamily != "NFTTransferPayload" &&
- columnFamily != "TokenTransferDetails" {
- fmt.Fprint(w, "columnFamily must be one of: ['TokenTransferPayload', 'AssetMetaPayload', 'NFTTransferPayload', 'TokenTransferDetails']")
- http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
- return
- }
- prefix := ""
- if emitterChain != "" {
- prefix = emitterChain
- if emitterAddress != "" {
- prefix = emitterChain + emitterAddress
- }
- }
- results := []bigtable.Row{}
- err := tbl.ReadRows(r.Context(), bigtable.PrefixRange(prefix), func(row bigtable.Row) bool {
- results = append(results, row)
- return true
- }, bigtable.RowFilter(
- bigtable.ConditionFilter(
- bigtable.ChainFilters(
- bigtable.FamilyFilter(columnFamily),
- bigtable.ColumnFilter(columnName),
- bigtable.ValueFilter(value),
- ),
- bigtable.ChainFilters(
- bigtable.PassAllFilter(),
- bigtable.LatestNFilter(1),
- ),
- bigtable.BlockAllFilter(),
- )))
- if err != nil {
- http.Error(w, "Error reading rows", http.StatusInternalServerError)
- log.Printf("tbl.ReadRows(): %v", err)
- return
- }
- details := []Details{}
- for _, result := range results {
- detail := makeDetails(result)
- details = append(details, *detail)
- }
- jsonBytes, err := json.Marshal(details)
- if err != nil {
- w.WriteHeader(http.StatusInternalServerError)
- w.Write([]byte(err.Error()))
- log.Println(err.Error())
- return
- }
- w.WriteHeader(http.StatusOK)
- w.Write(jsonBytes)
- }
|