Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(runtime): implement server.requestIp + node:http socket.address() #6165

Merged
merged 10 commits into from
Sep 29, 2023

Conversation

paperdave
Copy link
Member

What does this PR do?

Implements server.requestIp; Fixes #3540

Supersedes #4559, thank you Parzival for getting the initial work, mainly around actually getting to the IP address. I added port support, trying to optimize the # of calls, as well as implement a lightweight object for JS.

This also makes node:http socket.address/remoteAddress/remotePort/remoteFamily work

Does not fix #4660 but this probably lays out most of the work for it to work.

  • Documentation or TypeScript types (it's okay to leave the rest blank in this case)
  • Code changes

How did you verify your code works?

New tests.

Parzival-3141 and others added 8 commits September 7, 2023 14:14
Changed Request.uws_request to the new AnyRequestContext. This
allows grabbing the IP from a Request. Unfinished.
Currently using uws's requestIpAsText, which always returns a ipv6
string. We should return a `SocketAddress` object to the user instead,
which will contain the formatted address string and what type it is.
We'll have to use requestIpAsBinary and parse that ourselves.
@pi0
Copy link

pi0 commented Sep 29, 2023

Reposting from #3540 (comment), any hope of considering requestIP for the name? 🙈

Comment on lines 1606 to 1609
length = sprintf(b, "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x",
b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11],
b[12], b[13], b[14], b[15]);
*is_ipv6 = true;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this IPv6 formatter was taken from some usockets code. Maybe this can be later improved to a more intelligent IPv6 formatter. I don't know enough about ipv6 formatting to do this though.

Copy link
Collaborator

@Hanaasagi Hanaasagi Sep 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe some utils like inet_ntop.

// length == 16
if (length == @sizeOf(std.meta.FieldType(std.os.sockaddr.in6, .addr))) {
    // from binary to text form, store in new_buf
    _ = bun.c_ares.ares_inet_ntop(std.os.AF.INET6, &b, &new_buf, new_buf_len);
    const len_ = bun.len(bun.cast([*:0]u8, new_buf[0..]));
    // text form ip address
    const ip = new_buf[0..len_];
}

namespace Bun {
namespace JSSocketAddress {

static const NeverDestroyed<String> IPv4 = MAKE_STATIC_STRING_IMPL("IPv4");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this shouldn't be in the header

auto length = us_get_remote_address_info(b, (us_socket_t *)res, dest, port, (int*)is_ipv6);

if (length == 4) {
length = sprintf(b, "%u.%u.%u.%u", b[0], b[1], b[2], b[3]);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should use snprintf so that the length is always checked and there's no risk of buffer overflow

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this code is adapted from another part of uSockets

if b[0] is interpreted as a u8, then the max length of this string is 15

the longest ipv6 string is supposed to be 39 characters long, though i'm not certain if the sprintf would respect that bound.

the given b is always 64 bytes long, i don't think a length check is neccecary, but we can do it just to ensure these bounds.

@Jarred-Sumner
Copy link
Collaborator

I'm going to merge this so that it can be part of v1.0.4, but please address the feedback in your next PR

@Jarred-Sumner Jarred-Sumner merged commit 6afa781 into main Sep 29, 2023
16 of 21 checks passed
@Jarred-Sumner Jarred-Sumner deleted the server-request-ip branch September 29, 2023 10:39
@@ -2354,12 +2369,12 @@ declare module "bun" {
* ```js
* export default {
* async fetch(request, server) {
* return new Response(server.requestIp(request));
* return new Response(server.requestIP(request));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

@simylein simylein Sep 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? In the js world we use camelCase so why was this accepted?

Copy link
Contributor

@simylein simylein Sep 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you look at the official nodejs documentation https://nodejs.org/dist/latest-v20.x/docs/api/http.html you will find that all acronyms like http are not capitalised besides the first letter when used in camelCase. I think we should align ourself with that and not start writing acronyms in caps. Besides that, currently bun has no capitalised acronyms either so this would be our first (mis)step towards that path.

Copy link

@ryanwinchester ryanwinchester Sep 29, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Imagine Json.stringify... gross

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? In the js world we use camelCase so why was this accepted?

it was decided from: https://twitter.com/bunjavascript/status/1707690336494186919

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thing is this is a JavaScript convention not a nodeJS convention. As bun resides in the JS/TS world I think we should stick to that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? In the js world we use camelCase so why was this accepted?

it was decided from: https://twitter.com/bunjavascript/status/1707690336494186919

I think twitter is the worst place to ask for opinions regarding code but that's just me

@Starstalker-awe
Copy link

The lack of typescript definitions makes this kinda goofy, having to add // @ts-ignore every time I wanna use it

@simylein
Copy link
Contributor

Update your bun-types package

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
8 participants