mirror of
https://github.com/Xevion/glance.git
synced 2025-12-10 02:07:20 -06:00
Allow specifying method and request body
This commit is contained in:
@@ -1292,6 +1292,9 @@ Examples:
|
|||||||
| ---- | ---- | -------- | ------- |
|
| ---- | ---- | -------- | ------- |
|
||||||
| url | string | yes | |
|
| url | string | yes | |
|
||||||
| headers | key (string) & value (string) | no | |
|
| headers | key (string) & value (string) | no | |
|
||||||
|
| method | string | no | GET |
|
||||||
|
| body-type | string | no | json |
|
||||||
|
| body | any | no | |
|
||||||
| frameless | boolean | no | false |
|
| frameless | boolean | no | false |
|
||||||
| allow-insecure | boolean | no | false |
|
| allow-insecure | boolean | no | false |
|
||||||
| template | string | yes | |
|
| template | string | yes | |
|
||||||
@@ -1310,6 +1313,31 @@ headers:
|
|||||||
Accept: application/json
|
Accept: application/json
|
||||||
```
|
```
|
||||||
|
|
||||||
|
##### `method`
|
||||||
|
The HTTP method to use when making the request. Possible values are `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `OPTIONS` and `HEAD`.
|
||||||
|
|
||||||
|
##### `body-type`
|
||||||
|
The type of the body that will be sent with the request. Possible values are `json`, and `string`.
|
||||||
|
|
||||||
|
##### `body`
|
||||||
|
The body that will be sent with the request. It can be a string or a map. Example:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
body-type: json
|
||||||
|
body:
|
||||||
|
key1: value1
|
||||||
|
key2: value2
|
||||||
|
multiple-items:
|
||||||
|
- item1
|
||||||
|
- item2
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
body-type: string
|
||||||
|
body: |
|
||||||
|
key1=value1&key2=value2
|
||||||
|
```
|
||||||
|
|
||||||
##### `frameless`
|
##### `frameless`
|
||||||
When set to `true`, removes the border and padding around the widget.
|
When set to `true`, removes the border and padding around the widget.
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package glance
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
@@ -21,10 +22,14 @@ var customAPIWidgetTemplate = mustParseTemplate("custom-api.html", "widget-base.
|
|||||||
|
|
||||||
// Needs to be exported for the YAML unmarshaler to work
|
// Needs to be exported for the YAML unmarshaler to work
|
||||||
type CustomAPIRequest struct {
|
type CustomAPIRequest struct {
|
||||||
URL string `json:"url"`
|
URL string `yaml:"url"`
|
||||||
AllowInsecure bool `json:"allow-insecure"`
|
AllowInsecure bool `yaml:"allow-insecure"`
|
||||||
Headers map[string]string `json:"headers"`
|
Headers map[string]string `yaml:"headers"`
|
||||||
Parameters queryParametersField `json:"parameters"`
|
Parameters queryParametersField `yaml:"parameters"`
|
||||||
|
Method string `yaml:"method"`
|
||||||
|
BodyType string `yaml:"body-type"`
|
||||||
|
Body any `yaml:"body"`
|
||||||
|
bodyReader io.ReadSeeker `yaml:"-"`
|
||||||
httpRequest *http.Request `yaml:"-"`
|
httpRequest *http.Request `yaml:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +88,41 @@ func (req *CustomAPIRequest) initialize() error {
|
|||||||
return errors.New("URL is required")
|
return errors.New("URL is required")
|
||||||
}
|
}
|
||||||
|
|
||||||
httpReq, err := http.NewRequest(http.MethodGet, req.URL, nil)
|
if req.Body != nil {
|
||||||
|
if req.Method == "" {
|
||||||
|
req.Method = http.MethodPost
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.BodyType == "" {
|
||||||
|
req.BodyType = "json"
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.BodyType != "json" && req.BodyType != "string" {
|
||||||
|
return errors.New("invalid body type, must be either 'json' or 'string'")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch req.BodyType {
|
||||||
|
case "json":
|
||||||
|
encoded, err := json.Marshal(req.Body)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("marshaling body: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
req.bodyReader = bytes.NewReader(encoded)
|
||||||
|
case "string":
|
||||||
|
bodyAsString, ok := req.Body.(string)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("body must be a string when body-type is 'string'")
|
||||||
|
}
|
||||||
|
|
||||||
|
req.bodyReader = strings.NewReader(bodyAsString)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if req.Method == "" {
|
||||||
|
req.Method = http.MethodGet
|
||||||
|
}
|
||||||
|
|
||||||
|
httpReq, err := http.NewRequest(strings.ToUpper(req.Method), req.URL, req.bodyReader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -92,6 +131,10 @@ func (req *CustomAPIRequest) initialize() error {
|
|||||||
httpReq.URL.RawQuery = req.Parameters.toQueryString()
|
httpReq.URL.RawQuery = req.Parameters.toQueryString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if req.BodyType == "json" {
|
||||||
|
httpReq.Header.Set("Content-Type", "application/json")
|
||||||
|
}
|
||||||
|
|
||||||
for key, value := range req.Headers {
|
for key, value := range req.Headers {
|
||||||
httpReq.Header.Add(key, value)
|
httpReq.Header.Add(key, value)
|
||||||
}
|
}
|
||||||
@@ -126,6 +169,10 @@ func (data *customAPITemplateData) Subrequest(key string) *customAPIResponseData
|
|||||||
}
|
}
|
||||||
|
|
||||||
func fetchCustomAPIRequest(ctx context.Context, req *CustomAPIRequest) (*customAPIResponseData, error) {
|
func fetchCustomAPIRequest(ctx context.Context, req *CustomAPIRequest) (*customAPIResponseData, error) {
|
||||||
|
if req.bodyReader != nil {
|
||||||
|
req.bodyReader.Seek(0, io.SeekStart)
|
||||||
|
}
|
||||||
|
|
||||||
client := ternary(req.AllowInsecure, defaultInsecureHTTPClient, defaultHTTPClient)
|
client := ternary(req.AllowInsecure, defaultInsecureHTTPClient, defaultHTTPClient)
|
||||||
resp, err := client.Do(req.httpRequest.WithContext(ctx))
|
resp, err := client.Do(req.httpRequest.WithContext(ctx))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user