Add support for python function runtime
This commit is contained in:
16
app.py
16
app.py
@@ -48,7 +48,7 @@ app.register_blueprint(auth, url_prefix='/auth')
|
|||||||
# https://stackoverflow.com/questions/76886643/linking-two-not-exposed-dokku-apps
|
# https://stackoverflow.com/questions/76886643/linking-two-not-exposed-dokku-apps
|
||||||
NODE_API_URL = os.environ.get('NODE_API_URL', 'http://isolator.web:5000/execute')
|
NODE_API_URL = os.environ.get('NODE_API_URL', 'http://isolator.web:5000/execute')
|
||||||
DENO_API_URL = os.environ.get('DENO_API_URL', 'http://deno-isolator.web:5000/execute')
|
DENO_API_URL = os.environ.get('DENO_API_URL', 'http://deno-isolator.web:5000/execute')
|
||||||
|
PYTHON_API_URL = os.environ.get('PYTHON_API_URL', 'http://python-isolator.web:5000/execute')
|
||||||
|
|
||||||
def map_isolator_response_to_flask_response(response):
|
def map_isolator_response_to_flask_response(response):
|
||||||
"""
|
"""
|
||||||
@@ -84,7 +84,12 @@ async def execute_code():
|
|||||||
# Extract code and convert request to a format acceptable by Node.js app
|
# Extract code and convert request to a format acceptable by Node.js app
|
||||||
code = request.json.get('code')
|
code = request.json.get('code')
|
||||||
runtime = request.json.get('runtime', 'node') # Default to node
|
runtime = request.json.get('runtime', 'node') # Default to node
|
||||||
api_url = DENO_API_URL if runtime == 'deno' else NODE_API_URL
|
if runtime == 'deno':
|
||||||
|
api_url = DENO_API_URL
|
||||||
|
elif runtime == 'python':
|
||||||
|
api_url = PYTHON_API_URL
|
||||||
|
else:
|
||||||
|
api_url = NODE_API_URL
|
||||||
|
|
||||||
request_obj = {
|
request_obj = {
|
||||||
'method': request.method,
|
'method': request.method,
|
||||||
@@ -181,7 +186,12 @@ async def execute_http_function(user_id, function):
|
|||||||
request_data['text'] = request.data.decode('utf-8')
|
request_data['text'] = request.data.decode('utf-8')
|
||||||
|
|
||||||
# Call the Node.js API asynchronously
|
# Call the Node.js API asynchronously
|
||||||
api_url = DENO_API_URL if runtime == 'deno' else NODE_API_URL
|
if runtime == 'deno':
|
||||||
|
api_url = DENO_API_URL
|
||||||
|
elif runtime == 'python':
|
||||||
|
api_url = PYTHON_API_URL
|
||||||
|
else:
|
||||||
|
api_url = NODE_API_URL
|
||||||
async with aiohttp.ClientSession() as session:
|
async with aiohttp.ClientSession() as session:
|
||||||
async with session.post(api_url, json={'code': code, 'request': request_data, 'environment': environment, 'name': function_name}) as response:
|
async with session.post(api_url, json={'code': code, 'request': request_data, 'environment': environment, 'name': function_name}) as response:
|
||||||
response_data = await response.json()
|
response_data = await response.json()
|
||||||
|
|||||||
@@ -99,6 +99,11 @@ DEFAULT_ENVIRONMENT = """{
|
|||||||
"lines": 3
|
"lines": 3
|
||||||
}"""
|
}"""
|
||||||
|
|
||||||
|
DEFAULT_PYTHON_SCRIPT = """def main(request, environment):
|
||||||
|
print(f"Method: {request['method']}")
|
||||||
|
return {"body": "Hello from Python!"}
|
||||||
|
"""
|
||||||
|
|
||||||
http = Blueprint('http', __name__)
|
http = Blueprint('http', __name__)
|
||||||
|
|
||||||
@http.route("/overview", methods=["GET"])
|
@http.route("/overview", methods=["GET"])
|
||||||
@@ -117,9 +122,19 @@ def overview():
|
|||||||
def new():
|
def new():
|
||||||
user_id = current_user.id
|
user_id = current_user.id
|
||||||
if request.method == "GET":
|
if request.method == "GET":
|
||||||
|
context = {
|
||||||
|
'user_id': user_id,
|
||||||
|
'name': 'foo',
|
||||||
|
'script': DEFAULT_SCRIPT,
|
||||||
|
'default_python_script': DEFAULT_PYTHON_SCRIPT,
|
||||||
|
'environment_info': DEFAULT_ENVIRONMENT,
|
||||||
|
'is_public': False,
|
||||||
|
'log_request': True,
|
||||||
|
'log_response': False
|
||||||
|
}
|
||||||
if htmx:
|
if htmx:
|
||||||
return render_block(environment, 'dashboard/http_functions/new.html', 'page', user_id=user_id, name='foo', script=DEFAULT_SCRIPT, environment_info=DEFAULT_ENVIRONMENT, is_public=False, log_request=True, log_response=False)
|
return render_block(environment, 'dashboard/http_functions/new.html', 'page', **context)
|
||||||
return render_template("dashboard/http_functions/new.html", user_id=user_id, name='foo', script=DEFAULT_SCRIPT, environment_info=DEFAULT_ENVIRONMENT, is_public=False, log_request=True, log_response=False)
|
return render_template("dashboard/http_functions/new.html", **context)
|
||||||
try:
|
try:
|
||||||
name = request.json.get('name')
|
name = request.json.get('name')
|
||||||
script_content = request.json.get('script_content')
|
script_content = request.json.get('script_content')
|
||||||
|
|||||||
@@ -83,7 +83,9 @@ const Editor = {
|
|||||||
this.editorJS = ace.edit("js-editor");
|
this.editorJS = ace.edit("js-editor");
|
||||||
this.editorJS.setOptions({ maxLines: 100 });
|
this.editorJS.setOptions({ maxLines: 100 });
|
||||||
this.editorJS.setTheme("ace/theme/github_dark");
|
this.editorJS.setTheme("ace/theme/github_dark");
|
||||||
this.editorJS.session.setMode("ace/mode/javascript");
|
this.editorJS.session.setMode(
|
||||||
|
this.runtime === "python" ? "ace/mode/python" : "ace/mode/javascript"
|
||||||
|
);
|
||||||
this.editorJS.setValue(this.jsValue, -1);
|
this.editorJS.setValue(this.jsValue, -1);
|
||||||
|
|
||||||
this.editorJS.session.on("change", () => {
|
this.editorJS.session.on("change", () => {
|
||||||
@@ -397,61 +399,51 @@ const Editor = {
|
|||||||
|
|
||||||
// Right side: Runtime toggle and Execute button
|
// Right side: Runtime toggle and Execute button
|
||||||
m("div", { class: "flex items-center space-x-4" }, [
|
m("div", { class: "flex items-center space-x-4" }, [
|
||||||
// Runtime Toggle Switch
|
// Runtime Dropdown
|
||||||
m(
|
m(
|
||||||
"label",
|
"select",
|
||||||
{
|
{
|
||||||
for: "runtime-toggle",
|
key: "runtime-selector",
|
||||||
class: "inline-flex items-center cursor-pointer",
|
class:
|
||||||
|
"bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500",
|
||||||
|
onchange: (e) => {
|
||||||
|
this.runtime = e.target.value;
|
||||||
|
this.editorJS.session.setMode(
|
||||||
|
this.runtime === "python"
|
||||||
|
? "ace/mode/python"
|
||||||
|
: "ace/mode/javascript"
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
m(
|
m(
|
||||||
"span",
|
"option",
|
||||||
{
|
{ value: "node", selected: this.runtime === "node" },
|
||||||
class:
|
|
||||||
"mr-3 text-sm font-medium " +
|
|
||||||
(this.runtime === "node"
|
|
||||||
? "text-green-500"
|
|
||||||
: "text-gray-400 dark:text-gray-500"),
|
|
||||||
},
|
|
||||||
"Node"
|
"Node"
|
||||||
),
|
),
|
||||||
m("div", { class: "relative" }, [
|
|
||||||
m("input[type=checkbox]", {
|
|
||||||
id: "runtime-toggle",
|
|
||||||
class: "sr-only peer",
|
|
||||||
checked: this.runtime === "deno",
|
|
||||||
onchange: (e) => {
|
|
||||||
this.runtime = e.target.checked ? "deno" : "node";
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
m("div", {
|
|
||||||
class:
|
|
||||||
"w-11 h-6 bg-gray-200 rounded-full peer peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 dark:bg-gray-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-blue-600",
|
|
||||||
}),
|
|
||||||
]),
|
|
||||||
m(
|
m(
|
||||||
"span",
|
"option",
|
||||||
{
|
{ value: "deno", selected: this.runtime === "deno" },
|
||||||
class:
|
|
||||||
"ml-3 text-sm font-medium " +
|
|
||||||
(this.runtime === "deno"
|
|
||||||
? "text-blue-500"
|
|
||||||
: "text-gray-400 dark:text-gray-500"),
|
|
||||||
},
|
|
||||||
"Deno"
|
"Deno"
|
||||||
),
|
),
|
||||||
|
m(
|
||||||
|
"option",
|
||||||
|
{ value: "python", selected: this.runtime === "python" },
|
||||||
|
"Python"
|
||||||
|
),
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
|
|
||||||
this.executeLoading
|
this.executeLoading
|
||||||
? m("div", {
|
? m("div", {
|
||||||
|
key: "spinner",
|
||||||
class:
|
class:
|
||||||
"animate-spin h-6 w-6 border-4 border-green-300 border-t-transparent rounded-full",
|
"animate-spin h-6 w-6 border-4 border-green-300 border-t-transparent rounded-full",
|
||||||
})
|
})
|
||||||
: m(
|
: m(
|
||||||
"button",
|
"button",
|
||||||
{
|
{
|
||||||
|
key: "execute-button",
|
||||||
class: "p-2 rounded-full hover:bg-gray-200 text-green-700",
|
class: "p-2 rounded-full hover:bg-gray-200 text-green-700",
|
||||||
onclick: () => this.execute(),
|
onclick: () => this.execute(),
|
||||||
title: "Execute",
|
title: "Execute",
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ title='New HTTP Function')
|
|||||||
view: () => m(Editor, {
|
view: () => m(Editor, {
|
||||||
name: '{{ name }}',
|
name: '{{ name }}',
|
||||||
jsValue: {{ script | tojson | safe }},
|
jsValue: {{ script | tojson | safe }},
|
||||||
|
pythonValue: {{ default_python_script | tojson | safe }},
|
||||||
jsonValue: {{ environment_info | tojson | safe }},
|
jsonValue: {{ environment_info | tojson | safe }},
|
||||||
isEdit: false,
|
isEdit: false,
|
||||||
isAdd: true,
|
isAdd: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user