GithubHelp home page GithubHelp logo

gr7d / aqua Goto Github PK

View Code? Open in Web Editor NEW
221.0 5.0 7.0 204 KB

A minimal and fast 🏃 web framework for Deno

License: GNU Lesser General Public License v3.0

TypeScript 100.00%
deno web web-framework aqua middlewares cookies file-upload http-server typescript http

aqua's People

Contributors

felixfong227 avatar gr7d avatar mocoso avatar shyim avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

aqua's Issues

Alternative for app.render in 1.3.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?

[Question] File Uploading

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

Pass error type to the provided fallback handler

Maybe as a second argument, something like

enum ErrorType {
    NotFound,
    ErrorInResponseHandler,
    SchemaMismatch
}

type FallbackHandler = (req: Request, errorType: ErrorType) => Response | Promise<Response>;

Add application/x-www-form-urlencoded body parsing

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))
        }

Setting up Longpoll without Blocking

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);
    });
}

Add addMiddleware function

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.

req.cookies is not filled

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 :

image


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"];
}

Bundle error.

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

Спасибо!

URL parameters

Something like

app.get("/user/:user", (req) => {
    console.log(req.parameters.user)
});

Aqua v1.3.0 will drop support for Deno versions < 1.13

Downsides, that made me decide this way were:

  • std/http will be removed soon
  • There are no dynamic imports, so even when using a Deno version suitable for the native support, you would still have to download all std/http files

Feature Request: Wildcard Routing

Right now, I'm using app.provideFallback to handle serving assets. Do you have any plans for wildcard routing support? For example, app.get('/assets/*', ...).

static route at the root path does not work as expected

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.

Max Request Limit?

Hello is there a max request limit size? While testing my request in parseBody->rawBody seems to be truncated at around 2000 characters.

Cookies : add more control over creation

Hello, I'm still trying to create a my own session system.

However, when I create cookies using a response middleware, they are scoped to the path where they are created. Is it possible to make them global ?

image

Invalid route invoked

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.

Need Info! Static server

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')
})

Group feature

I think a group feature would be cool.
It should maybe have some of the following features.

  • Prefix
  • Middleware

Maybe something like:

app.group((context) => {
    context.get(...);
    ....
});

Add functions that replace req.respond

Functions like

req.setStatus(statusCode: number)
req.setCookie(name: string, value: string)
req.setHeader(name: string, value: string) // parameters probably not final

Redirect crash app

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!

2

how can I fix this?

How to send file upload request using javascript?

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?

Feature Request: serveTLS Support

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 });
}`

Idea of enhancement: Headers

Idea of enhancement

Maybe you'll like the idea of making an easy way to take headlines from headers.

Replication:

HTML

<form action="/test" method="post">
    <input type="text" name="name">
    <button type="submit"> ok </button>
</form>

<script src="fetch.js"></script>

fetch.js

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')
})

Server Side JS

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)
    })
    
})

Result

Screenshot_1

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!

Feature Request: GraphQL support

Do you have plan to support graphql like below?

  1. Developer can register graphql support like Middleware.
  2. GraphQL handler to simplified implementation.

Feature Request: view engine friendly support

Issue

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!

versions

Deno 1.7.5
Aqua 1.0.19

Schemas

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.

Response return type not exported

Summary

The RawResponse type is not exported from Aqua.

Details

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.

Expected

Export the RawResponse type.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.