httpproxy_wasm.mx raw

   1  //go:build wasm
   2  //:build wasm
   3  
   4  package httpproxy
   5  
   6  import (
   7  	"git.smesh.lol/smesh/web/common/jsbridge/callback"
   8  	"unsafe"
   9  )
  10  
  11  // === Consumer-side ===
  12  
  13  //:wasmimport bridge httpproxy_request
  14  func wasmRequest(reqID int32, urlPtr *byte, urlLen int32, urlCap int32, priority int32)
  15  
  16  //:wasmimport bridge httpproxy_request_cancel
  17  func wasmRequestCancel(reqID int32)
  18  
  19  type fetchHandler struct {
  20  	onOK   func(string, string)
  21  	onFail func(int32, string)
  22  }
  23  
  24  var pendingFetches = map[int32]fetchHandler{}
  25  
  26  func Request(reqID int32, url string, priority int32,
  27  	onOK func(blobURL, contentType string),
  28  	onFail func(status int32, errMsg string)) {
  29  	pendingFetches[reqID] = fetchHandler{onOK: onOK, onFail: onFail}
  30  	wasmRequest(reqID, unsafe.StringData(url), int32(len(url)), int32(len(url)), priority)
  31  }
  32  
  33  func RequestCancel(reqID int32) {
  34  	delete(pendingFetches, reqID)
  35  	wasmRequestCancel(reqID)
  36  }
  37  
  38  // __httpproxy_result_ok is the wasm export the supervisor calls when a
  39  // fetch succeeds. blobURL and contentType are the result strings.
  40  //
  41  //:wasmexport __httpproxy_result_ok
  42  func httpproxyResultOK(reqID int32, blobPtr *byte, blobLen int32, ctPtr *byte, ctLen int32) {
  43  	h, ok := pendingFetches[reqID]
  44  	if !ok {
  45  		return
  46  	}
  47  	delete(pendingFetches, reqID)
  48  	blobURL := ""
  49  	if blobLen > 0 {
  50  		blobURL = unsafe.String(blobPtr, blobLen)
  51  	}
  52  	contentType := ""
  53  	if ctLen > 0 {
  54  		contentType = unsafe.String(ctPtr, ctLen)
  55  	}
  56  	h.onOK(blobURL, contentType)
  57  }
  58  
  59  // __httpproxy_result_fail is the wasm export the supervisor calls when a
  60  // fetch fails. status is the upstream HTTP status (0 if no response).
  61  //
  62  //:wasmexport __httpproxy_result_fail
  63  func httpproxyResultFail(reqID int32, status int32, errPtr *byte, errLen int32) {
  64  	h, ok := pendingFetches[reqID]
  65  	if !ok {
  66  		return
  67  	}
  68  	delete(pendingFetches, reqID)
  69  	errMsg := ""
  70  	if errLen > 0 {
  71  		errMsg = unsafe.String(errPtr, errLen)
  72  	}
  73  	h.onFail(status, errMsg)
  74  }
  75  
  76  // === Worker-internal ===
  77  
  78  //:wasmimport bridge httpproxy_on_message
  79  func wasmOnMessage(cbID int32)
  80  
  81  //:wasmimport bridge httpproxy_post
  82  func wasmPost(ptr *byte, length int32, cap int32)
  83  
  84  //:wasmimport bridge httpproxy_fetch
  85  func wasmFetch(reqID int32, urlPtr *byte, urlLen int32, urlCap int32)
  86  
  87  //:wasmimport bridge httpproxy_cancel
  88  func wasmCancel(reqID int32)
  89  
  90  //:wasmimport bridge httpproxy_revoke_blob
  91  func wasmRevokeBlob(ptr *byte, length int32, cap int32)
  92  
  93  func OnMessage(fn func(msg string)) {
  94  	wasmOnMessage(callback.RegisterS(fn))
  95  }
  96  
  97  func Post(msg string) {
  98  	wasmPost(unsafe.StringData(msg), int32(len(msg)), int32(len(msg)))
  99  }
 100  
 101  func Fetch(reqID int32, url string) {
 102  	wasmFetch(reqID, unsafe.StringData(url), int32(len(url)), int32(len(url)))
 103  }
 104  
 105  func Cancel(reqID int32) {
 106  	wasmCancel(reqID)
 107  }
 108  
 109  func RevokeBlob(url string) {
 110  	wasmRevokeBlob(unsafe.StringData(url), int32(len(url)), int32(len(url)))
 111  }
 112