gr7d / aqua Goto Github PK
View Code? Open in Web Editor NEWA minimal and fast 🏃 web framework for Deno
License: GNU Lesser General Public License v3.0
A minimal and fast 🏃 web framework for Deno
License: GNU Lesser General Public License v3.0
Hi,
I've just tried the latest version 1.3.0.
When trying to render an HTML document, I got this error message:
Property 'render' does not exist on type 'Aqua'.deno-ts(2339)
Checking the release notes, I've found that render
is "removed from the public Aqua class".
It seemed simple and intuitive enough, so I'm wondering why the remove?
What is the recommended way for serving HTML files from now on?
Both while browsing deno.land and while importing the framework, the latest version cannot be found.
app.route("/", "GET", (req) => {
req.respond({ body: "Hello world!" });
});
would become
app.route("/", "GET", (req) => {
return "Hello world!";
});
Would be more dev-friendly
So I saw in the README that Aqua supports uploading Files (or Images at least).
I'm kind wondering what code I'd need to write to support uploading files for my small server app.
I'm currently using insomnia.rest, which supports Multipart Forms and binary file uploads but I don't really understand how to actually write the code needed to get the small snippet at the end of the readme to work how it should
Maybe as a second argument, something like
enum ErrorType {
NotFound,
ErrorInResponseHandler,
SchemaMismatch
}
type FallbackHandler = (req: Request, errorType: ErrorType) => Response | Promise<Response>;
This can be done pretty easily by adding some code to parseBody:
(Please ignore the changes I made to get it working in JS and extracting the body)
function parseBody(req) {
var textDecoder = new TextDecoder();
const rawBody = textDecoder.decode(req.raw.r.buf);
let body = {};
if (!rawBody) return {};
try {
body = JSON.parse(rawBody);
}catch(error) {
if (rawBody.includes('name="')) { //multipart/form-data
body = (rawBody.match(/name="(.*?)"(\s|\n|\r)*(.*)(\s|\n|\r)*---/gm) || [])
.reduce((fields, field) => {
if (!/name="(.*?)"/.exec(field)?.[1]) return fields;
return {
...fields,
[/name="(.*?)"/.exec(field)?.[1] || ""]: field.match(/(.*?)(?=(\s|\n|\r)*---)/)?.[0]
}
}, {});
} else { //application/x-www-form-urlencoded
const urlParamsStr = rawBody.substr(rawBody.indexOf('\r\n\r\n')+4);
body = Object.fromEntries(new URLSearchParams(urlParamsStr))
}
}
return body;
}
This is the part that does the x-www-form-urlencode parsing:
} else { //application/x-www-form-urlencoded
const urlParamsStr = rawBody.substr(rawBody.indexOf('\r\n\r\n')+4);
body = Object.fromEntries(new URLSearchParams(urlParamsStr))
}
Maybe something like:
app.get("/", (req) => {
return { redirect: "/hello" };
});
Hi,
I am trying to setup a longpoll example, but I am having an issue with subsequent requests being blocked. Can you take a look at the following example?
Test Endpoints
-start the longpoll request (waits up to 10 seconds)
http://localhost/longpoll/
-test (doesn't return until longpoll is done)
http://localhost/test/
-toggle longpoll variable
http://localhost/toggle/
Example Code
//imports
import Aqua from "https://deno.land/x/aqua/mod.ts";
//global variables
const app = new Aqua(80);
let bChange = false;
//test
app.get("/test/", async (req) => {
bChange = (bChange ? false : true);
return {
statusCode: 200,
headers: { "Content-Type": "application/json" },
content: JSON.stringify('test')
};
});
//toggle
app.get("/toggle/", async (req) => {
bChange = (bChange ? false : true);
return {
statusCode: 200,
headers: { "Content-Type": "application/json" },
content: JSON.stringify(bChange)
};
});
//longpoll
app.get("/longpoll/", async (req) => {
await waitFor(()=>bChange, 10000, 100);
return {
statusCode: 200,
headers: { "Content-Type": "application/json" },
content: JSON.stringify("Done polling")
};
});
//functions
function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
async function waitFor(test, timeout_ms = 20*2000, frequency = 100){
return new Promise( async (resolve,reject) => {
if( typeof(timeout_ms) != "number") reject("Timeout argument not a number in waitFor(test, [timeout_ms], [frequency])");
let result
// wait until the result is truthy, or timeout
while( result === undefined || result === false || result === null || result.length === 0 ){ // for non arrays, length is undefined, so != 0
timeout_ms -= frequency;
if( timeout_ms < 0 ){
resolve(false);
return;
}
await sleep(frequency);
result = test();
}
// return result if test passed
resolve(result);
});
}
File uploading would be a great feature, I think.
The addMiddleware
function should allow the execution of a specific statements before the response is getting sent.
It's probably important to pass specific values within the scope.
Log more important information (for example at the body parsing part)
Hello,
I'm actually creating a session system for my project. I need to read and store a session id from cookie.
Expected behavior : if the user holds a cookie with name session
, then a controller requesting req.cookies.session
should hold the cookie value
Current behavior : the object req.cookies
is an empty object. However, req.headers.cookie
contains the raw data so a quickfix is easy.
Screenshot :
Also, when I save values in req.cookie, I need to use the following code in an outgoing middleware to sync with res.cookie
if (!res.cookies["session"]) {
res.cookies["session"] = req.cookies["session"];
}
Support Deno Deploy by default
Something like
app.get("/", (req) => {
return { statusCode: 404, headers: {}, content: "Mhm" };
});
IF i run command deno bundle https://deno.land/x/[email protected]/mod.ts aqua.js
and run with local import - i see the error.
But if download repository and delete this lines in mod.ts -
import Aqua from "./aqua.ts";
export default Aqua;
can be run bundler locally - deno bundle mod.ts aqua.js
and run again - everything works fine.
(warning - in deno 1.6.3 new bundler and there are often problems with it, i make bundle with 1.5.4 version)
You may find this observation useful
Спасибо!
Hello,
i need ? parameters for my login, e.g. localhost:3100/login?code=supercoolcode
Are they already implemented?
Something like
app.get("/user/:user", (req) => {
console.log(req.parameters.user)
});
Downsides, that made me decide this way were:
std/http
will be removed soonstd/http
filesRight now, I'm using app.provideFallback
to handle serving assets. Do you have any plans for wildcard routing support? For example, app.get('/assets/*', ...)
.
Hello, in a first place, thanks to the dev, this is a very nice library !
I'm trying to embed a basic front-end with aqua. I created the following code :
const app: Aqua = new Aqua(3000);
app.serve("web-front", "/");
Expected Behavior : Going to localhost:3000/index.html
should show file web-front/index.html
Current Behavior:
localhost:3000/index.html
produces a 404 error.localhost:3000//index.html
does the expected result.Hello is there a max request limit size? While testing my request in parseBody->rawBody seems to be truncated at around 2000 characters.
For example :
app.get("/:filename", (req) => {
console.log(req.parameters.filename);
}
Visit url using localhost:port/abc.html, log's output is abc, not abc.html
How to get user ip address
While experimenting with Aqua, I found an issue with how routes are invoked. Given the following routes:
app.get('/:key', GetKey)
app.post('/:key/:value', SetKey)
A GET request to /hello/world
will invoke SetKey
function, which should only be ran in case of a POST request.
I believe the problem lies in Router.findRouteWithMatchingURLParameters, where the route's method is not taken into account.
Same issue as described here;
Jozty/Fae#32
As I see currently it's not possible to manipulate the response?
I was thinking about a session middleware
Hi! I'm new to backend, I hope for your help!
I run this example, but CSS style dont work!
Of course styles are connected in HTML
import Aqua from 'https://deno.land/x/aqua/mod.ts'
const app = new Aqua(3100)
app.get('/', async (req) => {
return await app.render('static/index.html')
})
Sometimes, the following error appears randomly when I do a request :
error: Uncaught (in promise) Http: connection closed before message completed
at Object.respondWith (deno:ext/http/01_http.js:254:21)
Unfortunately, I don't have further information. I can't even reproduce sometimes.
The following github issue and linked threads might help : denoland/deno#13203
I think a group feature would be cool.
It should maybe have some of the following features.
Maybe something like:
app.group((context) => {
context.get(...);
....
});
Functions like
req.setStatus(statusCode: number)
req.setCookie(name: string, value: string)
req.setHeader(name: string, value: string) // parameters probably not final
Hi.
I wrote simple test and want share it with you.
Code with your examples:
import Aqua from 'https://deno.land/x/aqua/mod.ts'
const app = new Aqua(8080)
app.serve('static', '/')
app.get('/', async (request) => {
return await app.render('static/index.html')
})
app.get('/test.html', (request) => {
return {
redirect: '/'
}
})
app.post('/test', (request) => {
return {
redirect: '/testRedirect'
}
})
app.register((req, res) => {
const testData = 'Test string'
res.content = res.content.replace('- aquaTest -', testData)
return res
})
// deno run --allow-read --allow-write --allow-net --watch --unstable app.js
run it!
how can I fix this?
I'm using your demo code to run a sample upload server:
`import Aqua from "https://deno.land/x/aqua/mod.ts";
const app = new Aqua(3100);
app.get("/", (req) => {
return "Hello, World!";
});
app.post("/upload", async (req) => {
const { newProfilePicture } = req.files;
//return newProfilePicture;
await Deno.writeFile(newProfilePicture.name , new Uint8Array(await newProfilePicture.arrayBuffer()));
return "Uploaded!";
});`
But told me : error: Uncaught (in promise) TypeError: Cannot read property 'name' of undefined
await Deno.writeFile(newProfilePicture.name , new Uint8Array(await newProfilePicture.arrayBuffer()));
My access code is like below:
var resp = await fetch("http://127.0.0.1:3100/upload", { method: "POST", headers: [["Content_Type","multipart/form-data"],["Content-Disposition","attachment; filename=test"] ], body: dataToSend });
Would you give me right sample code using javascript which can upload file successfully?
The render
function currently doesn't set the right "Content-Type" header.
Great web framework! Any plans to implement https?
`import { serveTLS } from "https://deno.land/std/http/server.ts";
const body = new TextEncoder().encode("Hello HTTPS");
const options = {
hostname: "localhost",
port: 443,
certFile: "./path/to/localhost.crt",
keyFile: "./path/to/localhost.key",
};
for await (const req of serveTLS(options)) {
req.respond({ body });
}`
Maybe you'll like the idea of making an easy way to take headlines from headers
.
Replication:
<form action="/test" method="post">
<input type="text" name="name">
<button type="submit"> ok </button>
</form>
<script src="fetch.js"></script>
const form = document.querySelector('form')
// function
const request = async (url) => {
const data = new FormData(form)
const options = {
method: 'POST',
cache: 'no-cache',
headers: {
TEST: 'maybe_localStorage_token...',
},
body: data
}
const req = await fetch(url, options)
const res = await req.json()
}
// send on submit
form.addEventListener('submit', (event) => {
event.preventDefault()
request('http://localhost:3100/test')
})
import Aqua from 'https://deno.land/x/aqua/mod.ts'
const app = new Aqua(3100)
app.serve('static', '/')
app.get('/', async (request, response) => {
return await app.render('static/index.html')
})
app.post('/test', async (request, response) => {
const headers = request.headers
console.log(headers)
headers.forEach(el => {
console.log(el)
})
})
It is not convenient to take values. Maybe it will be better to take the value like this:
app.post('/test', async (request, response) => {
const token = request.headers.get('test')
console.log(token)
})
// maybe_localStorage_token...
Thanks!
Do you have plan to support graphql like below?
The headers
type differs on the request and the response
Hello!
Is it possible to add seamless DEJS support?
Like this:
import Aqua from 'https://deno.land/x/aqua/mod.ts'
import { renderFile } from 'https://deno.land/x/[email protected]/mod.ts'
const app = new Aqua(3100)
app.serve('static', '/')
app.get('/', async (request, response) => {
return await renderFile('static/index.html', {
test: 'test string render',
})
})
Example:
https://deno.land/x/[email protected]/examples/template/main.ts
If I missed something, please add an example!
Deno 1.7.5
Aqua 1.0.19
An easy schema implementation to validate requests more easily.
A 4th argument for the route function would be a nice fit.
Maybe something like:
app.route("/", "POST", (req) => "Hello, World!", {
schema: {
body: {
accessKey: "string"
}
}
});
...or:
import Aqua, { mustContain } from ...
app.route("/", "POST", (req) => "Hello, World!", {
schema: {
body: [
mustContain("accessKey", "string")
]
}
});
This would make it easier to extend the methods and possibilities later.
The RawResponse
type is not exported from Aqua.
In this line, the RawResponse
type is defined, but not exported. This makes it more difficult to apply the proper response types to functions.
To keep my application more structured, I use controller classes to keep this logic together. Since I cannot typehint my controllers, I'll have to rely on Deno providing enough information to the IDE, and the IDE to interpret this properly, which not all IDEs do.
Export the RawResponse
type.
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.