FUNCTION: Handles a Connected-Client "function" request. - Function name is in the "name" property. - Arguments (optional) are JSON-encoded in the body.
(rq *blip.Message)
| 89 | // - Function name is in the "name" property. |
| 90 | // - Arguments (optional) are JSON-encoded in the body. |
| 91 | func (bh *blipHandler) handleFunction(rq *blip.Message) error { |
| 92 | name, found := rq.Properties[QueryName] |
| 93 | if !found { |
| 94 | return base.HTTPErrorf(http.StatusBadRequest, "Missing 'name'") |
| 95 | } |
| 96 | |
| 97 | requestParams, err := bh.parseJsonBody(rq, bh.db.Options.UserFunctions.MaxRequestSize) |
| 98 | if err != nil { |
| 99 | return err |
| 100 | } |
| 101 | |
| 102 | bh.logEndpointEntry(rq.Profile(), fmt.Sprintf("name: %s", name)) |
| 103 | return WithTimeout(bh.loggingCtx, bh.db.UserFunctionTimeout, func(ctx context.Context) error { |
| 104 | // Call the function: |
| 105 | fn, err := bh.db.GetUserFunction(ctx, name, requestParams, true) |
| 106 | if err != nil { |
| 107 | return err |
| 108 | } |
| 109 | |
| 110 | if iter, err := fn.Iterate(); err != nil { |
| 111 | return err |
| 112 | } else if iter != nil { |
| 113 | // Write each iterated result to the response: |
| 114 | defer func() { |
| 115 | if iter != nil { |
| 116 | _ = iter.Close() |
| 117 | } |
| 118 | }() |
| 119 | var out bytes.Buffer |
| 120 | enc := base.JSONEncoder(&out) |
| 121 | var row interface{} |
| 122 | for iter.Next(bh.loggingCtx, &row) { |
| 123 | if err = enc.Encode(row); err != nil { // always ends with a newline |
| 124 | return err |
| 125 | } |
| 126 | if err = CheckTimeout(ctx); err != nil { |
| 127 | return err |
| 128 | } |
| 129 | } |
| 130 | err = iter.Close() |
| 131 | iter = nil |
| 132 | if err != nil { |
| 133 | return err |
| 134 | } |
| 135 | response := rq.Response() |
| 136 | response.SetCompressed(true) |
| 137 | response.SetJSONBodyAsBytes(out.Bytes()) |
| 138 | return nil |
| 139 | |
| 140 | } else { |
| 141 | // Write the single result to the response: |
| 142 | result, err := fn.Run(bh.loggingCtx) |
| 143 | if err != nil { |
| 144 | return err |
| 145 | } |
| 146 | response := rq.Response() |
| 147 | response.SetCompressed(true) |
| 148 | _ = response.SetJSONBody(result) |
nothing calls this directly
no test coverage detected