devopifex / ambiorix Goto Github PK
View Code? Open in Web Editor NEW🖥️ Web framework for R
Home Page: http://ambiorix.dev
License: GNU General Public License v3.0
🖥️ Web framework for R
Home Page: http://ambiorix.dev
License: GNU General Public License v3.0
response_*
family does not feel right
Add tests.
Need input/ideas on how to do this best for web servers, .e.g.: mock requests, etc.
Remove template path restriction
We are going to need a better path matching process, e.g. path-to-regexp
Add listen to pass port
Add res$redirect()
Parse headers on the request to easily fetch them.
Add tests
Port option à la shiny to avoid running the app on a different port every time (dev iteration)
Using tailwind with ambiorix should be straightforward but we may want functionalities to make it even easier.
Two changes needed to make this work with the master version.
# app.R library(ambiorix) library(htmltools) library(mime) app <- Ambiorix$new() app$get("/", function(req, res){ # form # sends to /submit form <- tagList( tags$form( action = "/submit", enctype = "multipart/form-data", method = "POST", p( tags$label('for' = "first_name", "First Name"), tags$input(type = "text", name = "first_name") ), tags$input(type = "submit") ) ) res$send(form) }) app$post("/submit", function(req, res){ body <- parse_multipart(req$body) res$send(h1("Your name is", body$first_name)) }) app$start()
RUN R -e "install.packages('mime')"
Then the post example works with my docker test server.
Nice work!
Stephen
Parsers to parse results: json, xml, multipart, etc.
Hi @JohnCoene,
Recently I updated https://web-frameworks-benchmark.netlify.app/result.
After digging about ambiorix
results, I find that this package is not available anymore in CRAN
https://cran.r-project.org/package=ambiorix
The description I use in https://github.com/the-benchmarker/web-frameworks/blob/0826fd3bb0e0b5827285e0ac2107ccee4dcbf9df/r/ambiorix/DESCRIPTION#L1
Regards,
I found this example in the doco for response headers:
app$get("/hello", \(req, res){
res$header("Content-Type", "something")
res$send("Using {ambiorix}!")
})
The problem is that send()
has a default for the headers
arg: content_html()
which will replace the custom Content-Type
header something
with text/html
.
Templates differ, see generator: should be deprecated and moved to ambiorix.generator
Allow bypassing the websocket convenience.
A minimal hello world example of {ambiorix} gives an error log
app <- ambiorix::Ambiorix$new()
app$get("/", \(req, res) {
res$send("Hello World!")
})
app$start()
✔ 07-01-2024 13:14:16 Listening on http://localhost:31739
Error in inerits(x, "error") : could not find function "inerits"
> ℹ 07-01-2024 13:14:16 GET on /
✖ 07-01-2024 13:14:16 GET on /favicon.ico - Not found
The line below should be inherits
instead of inherits.
https://github.com/devOpifex/ambiorix/blob/12727999880ce581fafee391458109c9a443e51e/R/utils.R#L20
Hi,
I was trying to send an htmlwidget using res$htmlwidget()
, but the app kept insisting that the package is not installed. It seems like check_installed()
logic is flipped, i.e. it is throwing an error when the package is installed.
Add support for more serialisers
Allow setting response status with status method
Enable user sessions
Handle future for asynchronous requests
Add router for nested path
Add a convenience function to create templates
Allow passing function on server close.
Before import("views"), I needed to add a working directory at the root of template app:
# app.R is in /myapps/template01 setwd("/myapps/template01")
Then it worked. Without this addition, I observed this error:
Error: [ENOENT] Failed to search directory '//views': no such file or directory
Perhaps I overlooked a more elegant solution?
Best,
Stephen
Add serialisers, png, json, XML, htmlwidgets, etc.
Better error handling + add 500 (like 404 currently existing)
Hi John, good start on the abiorix package! I checked it out and run into 2 issues when parsing the request body.
(1) 1st thing is easy: parse_json
is not exported, so add #' @export
to R/parser.R
.
(2) But even when I used :::
still got ERROR: attempt to apply non-function
. Here is what I had for my Hello World example:
library(ambiorix)
app <- Ambiorix$new()
handle <- function(req) {
body <- ambiorix:::parse_json(req)
paste0('Hello ', body, '!')
}
app$post('/', function(req, res){
res$json(handle(req))
})
app$start()
Maybe it is a content type issue, but something is definitely not right here. Thanks!
Hello @JohnCoene, I think that one thing that is missing in your documentation is a section about comparing strengths and weaknesses of ambiorix
and shiny
. As someone who first discovered R, then shiny, and then the world of web development (probably as several shiny
users), I don't know what express.js
is and I don't know why it is useful.
As you say in this section:
Designing applications will, in all likelihood, always be faster with Shiny.
As a reader, when I see this, my reaction is more or less: then why should I use ambiorix
? I know that you show some examples in the docs, but the syntax is very different from shiny
and it seems quite complicated. I think there should be a section where you show/explain common shiny problems, and how ambiorix
makes it easier to solve them. Also, as a side question, is ambiorix
a lot different than brochure
?
I don't want this to sound as a criticism, I'm just trying to figure out if I should learn more about express.js
and ambiorix
. Thanks again for all this open source collection of tools! (PS: love the docs and the pictures used)
Ambiorix's error handling does not seem to work. It always sends the actual error message to the client.
library(ambiorix)
app <- Ambiorix$new()
app$get("/", \(req, res) {
res$send("Hello, World!")
})
# simulate error (object 'Pikachu' is not defined)
app$get("/whoami", \(req, res) {
print(Pikachu)
})
# `not_found` works as expected✅
app$not_found <- \(req, res) {
res$status <- 404L
res$send("Oops, the page you're looking for was not found!")
}
# `error` does NOT work as expected❌
# Instead of sending this to the client, it sends the actual
# error message
app$error <- \(req, res) {
res$status <- 500L
res$send("Uhhmmm... Looks like there's an error from our side :(")
}
app$start(port = 8000L, open = FALSE)
When an error occurs, it should send the customized message instead of the actual error message. For purposes of security.
Create dockerfile for deploy
Neat package!
I used it to conjure up a vector tile server with very little code, but I'm having a problem, which I think is because my tile data (raw vector) is getting transformed to text by the as.character()
in res$send()
. There doesn't seem to a res$send
variant that will let me send my data as binary (Content-Type: application/x-protobuf
).
Would you consider adding this? Or accepting a PR?
Allow app creating logs
Allow csv and tsv responses in plain text (not automatic download)
We should minify the HTML, CSS, etc.
Project:
The goal is an API which queries a database. Results set length varies a lot and so does the response time. In order to avoid blocking of fast queries by slow ones the API should by async.
Problem:
future
does not allow for external pointers (such as DB connections, pool
connections, etc.), thus I had to open a new DB connection (within future
) for every request which slows down response time significantly
I am looking for a solution based on this example with a non-blocking query_db()
functionality within the future.
Any help would be greatly appreciated!
library(future)
library(ambiorix)
plan(multisession)
app <- Ambiorix$new()
app$get("/async", function(req, res){
future({
dat <- query_db()
res$send(dat)
})
})
app$start()
Add send_file
: template but without rendering
Add favicon
Will help user doing the transition
Allow using next to use next method
Hi @JohnCoene . The inst/app.R file have a spelling error,
ibrary(ambiorix)
Deploy docs
Support R templates in response
family (htmltools
tags)
Allow mocking response and request to enable #48
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.