switch to python
This commit is contained in:
parent
0e688f08e9
commit
1b0177a6f0
35
README.md
35
README.md
@ -1,20 +1,29 @@
|
|||||||
# Go HTTP Function
|
# Python HTTP Function
|
||||||
|
|
||||||
Welcome to your new Go Function! The boilerplate function code can be found in
|
Welcome to your new Python function project! The boilerplate function
|
||||||
[`handle.go`](handle.go). This Function responds to HTTP requests.
|
code can be found in [`func.py`](./func.py). This function will respond
|
||||||
|
to incoming HTTP GET and POST requests.
|
||||||
|
|
||||||
## Development
|
## Endpoints
|
||||||
|
|
||||||
Develop new features by adding a test to [`handle_test.go`](handle_test.go) for
|
Running this function will expose three endpoints.
|
||||||
each feature, and confirm it works with `go test`.
|
|
||||||
|
|
||||||
Update the running analog of the function using the `func` CLI or client
|
* `/` The endpoint for your function.
|
||||||
library, and it can be invoked from your browser or from the command line:
|
* `/health/readiness` The endpoint for a readiness health check
|
||||||
|
* `/health/liveness` The endpoint for a liveness health check
|
||||||
|
|
||||||
|
The health checks can be accessed in your browser at
|
||||||
|
[http://localhost:8080/health/readiness]() and
|
||||||
|
[http://localhost:8080/health/liveness]().
|
||||||
|
|
||||||
|
You can use `func invoke` to send an HTTP request to the function endpoint.
|
||||||
|
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
This function project includes a [unit test](./test_func.py). Update this
|
||||||
|
as you add business logic to your function in order to test its behavior.
|
||||||
|
|
||||||
```console
|
```console
|
||||||
curl http://myfunction.example.com/
|
python test_func.py
|
||||||
```
|
```
|
||||||
|
|
||||||
For more, see [the complete documentation]('https://github.com/knative/func/tree/main/docs')
|
|
||||||
|
|
||||||
|
|
||||||
|
3
app.sh
Executable file
3
app.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
exec python -m parliament "$(dirname "$0")"
|
63
func.py
Normal file
63
func.py
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
from parliament import Context
|
||||||
|
from flask import Request
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
# parse request body, json data or URL query parameters
|
||||||
|
def payload_print(req: Request) -> str:
|
||||||
|
if req.method == "POST":
|
||||||
|
if req.is_json:
|
||||||
|
return json.dumps(req.json) + "\n"
|
||||||
|
else:
|
||||||
|
# MultiDict needs some iteration
|
||||||
|
ret = "{"
|
||||||
|
|
||||||
|
for key in req.form.keys():
|
||||||
|
ret += '"' + key + '": "'+ req.form[key] + '", '
|
||||||
|
|
||||||
|
return ret[:-2] + "}\n" if len(ret) > 2 else "{}"
|
||||||
|
|
||||||
|
elif req.method == "GET":
|
||||||
|
# MultiDict needs some iteration
|
||||||
|
ret = "{"
|
||||||
|
|
||||||
|
for key in req.args.keys():
|
||||||
|
ret += '"' + key + '": "' + req.args[key] + '", '
|
||||||
|
|
||||||
|
return ret[:-2] + "}\n" if len(ret) > 2 else "{}"
|
||||||
|
|
||||||
|
|
||||||
|
# pretty print the request to stdout instantaneously
|
||||||
|
def pretty_print(req: Request) -> str:
|
||||||
|
ret = str(req.method) + ' ' + str(req.url) + ' ' + str(req.host) + '\n'
|
||||||
|
for (header, values) in req.headers:
|
||||||
|
ret += " " + str(header) + ": " + values + '\n'
|
||||||
|
|
||||||
|
if req.method == "POST":
|
||||||
|
ret += "Request body:\n"
|
||||||
|
ret += " " + payload_print(req) + '\n'
|
||||||
|
|
||||||
|
elif req.method == "GET":
|
||||||
|
ret += "URL Query String:\n"
|
||||||
|
ret += " " + payload_print(req) + '\n'
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def main(context: Context):
|
||||||
|
"""
|
||||||
|
Function template
|
||||||
|
The context parameter contains the Flask request object and any
|
||||||
|
CloudEvent received with the request.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Add your business logic here
|
||||||
|
print("Received request")
|
||||||
|
|
||||||
|
if 'request' in context.keys():
|
||||||
|
ret = pretty_print(context.request)
|
||||||
|
print(ret, flush=True)
|
||||||
|
return payload_print(context.request), 200
|
||||||
|
else:
|
||||||
|
print("Empty request", flush=True)
|
||||||
|
return "{}", 200
|
@ -1,7 +1,7 @@
|
|||||||
specVersion: 0.35.0
|
specVersion: 0.35.0
|
||||||
name: hello
|
name: hello2
|
||||||
runtime: go
|
runtime: python
|
||||||
created: 2023-12-07T19:54:11.056629+01:00
|
created: 2023-12-08T16:20:58.104476+01:00
|
||||||
build:
|
build:
|
||||||
git:
|
git:
|
||||||
url: https://git.le-maire.eu/alemaire/knative-function.git # required, git repository with the function source code
|
url: https://git.le-maire.eu/alemaire/knative-function.git # required, git repository with the function source code
|
||||||
|
41
handle.go
41
handle.go
@ -1,41 +0,0 @@
|
|||||||
package function
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Handle an HTTP Request.
|
|
||||||
func Handle(ctx context.Context, res http.ResponseWriter, req *http.Request) {
|
|
||||||
/*
|
|
||||||
* YOUR CODE HERE
|
|
||||||
*
|
|
||||||
* Try running `go test`. Add more test as you code in `handle_test.go`.
|
|
||||||
*/
|
|
||||||
|
|
||||||
fmt.Println("Received request")
|
|
||||||
fmt.Println(prettyPrint(req)) // echo to local output
|
|
||||||
fmt.Fprintf(res, prettyPrint(req)) // echo to caller
|
|
||||||
}
|
|
||||||
|
|
||||||
func prettyPrint(req *http.Request) string {
|
|
||||||
b := &strings.Builder{}
|
|
||||||
fmt.Fprintf(b, "%v %v %v %v\n", req.Method, req.URL, req.Proto, req.Host)
|
|
||||||
for k, vv := range req.Header {
|
|
||||||
for _, v := range vv {
|
|
||||||
fmt.Fprintf(b, " %v: %v\n", k, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if req.Method == "POST" {
|
|
||||||
req.ParseForm()
|
|
||||||
fmt.Fprintln(b, "Body:")
|
|
||||||
for k, v := range req.Form {
|
|
||||||
fmt.Fprintf(b, " %v: %v\n", k, v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return b.String()
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
package function
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TestHandle ensures that Handle executes without error and returns the
|
|
||||||
// HTTP 200 status code indicating no errors.
|
|
||||||
func TestHandle(t *testing.T) {
|
|
||||||
var (
|
|
||||||
w = httptest.NewRecorder()
|
|
||||||
req = httptest.NewRequest("GET", "http://example.com/test", nil)
|
|
||||||
res *http.Response
|
|
||||||
)
|
|
||||||
|
|
||||||
Handle(context.Background(), w, req)
|
|
||||||
res = w.Result()
|
|
||||||
defer res.Body.Close()
|
|
||||||
|
|
||||||
if res.StatusCode != 200 {
|
|
||||||
t.Fatalf("unexpected response code: %v", res.StatusCode)
|
|
||||||
}
|
|
||||||
}
|
|
1
requirements.txt
Normal file
1
requirements.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
parliament-functions==0.1.0
|
13
test_func.py
Normal file
13
test_func.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
|
func = __import__("func")
|
||||||
|
|
||||||
|
class TestFunc(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_func_empty_request(self):
|
||||||
|
resp, code = func.main({})
|
||||||
|
self.assertEqual(resp, "{}")
|
||||||
|
self.assertEqual(code, 200)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
Loading…
Reference in New Issue
Block a user