Git Product home page Git Product logo

avaje-jex's People

Contributors

rbygrave avatar rob-bygrave avatar

Stargazers

 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  avatar

avaje-jex's Issues

ENH: Add Context.jsonStream(...) to write x-json-stream content from Stream<E> or Iterator<E>

  /**
   * Write the stream as a JSON stream with new line delimiters
   * {@literal application/x-json-stream}.
   *
   * @param stream The stream of beans to write as json
   */
  <E> Context jsonStream(Stream<E> stream);

  /**
   * Write the stream as a JSON stream with new line delimiters
   * {@literal application/x-json-stream}.
   *
   * @param iterator The iterator of beans to write as json
   */
  <E> Context jsonStream(Iterator<E> iterator);

Note that when using Iterator internally it will check if the instance implements AutoCloseable and if so will close the iterator when all elements have been written. Stream implements AutoCloseable so that also gets closed.

Auto-detection of JsonService additionally supports avaje-jsonb (so detects Jackson, then avaje-jsonb)

So when a JsonService is not explicitly set, if Jackson is present then that is used, if avaje-jsonb is present then it is used.

For people who don't know what avaje-jsonb is, TLDR - it's a source code generation approach to json binding (so light and fast). It comes with it's own underlying parser/generator but can also use jackson-core under the hood for people wanting to use that (heavier, slower but it's jackson core with a few more features and people love jackson etc).

Add BootJex ... for easy starting when using @Controller etc

Example use:

public static void main(String[] args) {
  BootJex.start();
}

Docs

package io.avaje.jex;

/**
 * Start Jex using {@code @Controller} and avaje-inject, avaje-http, avaje-config.
 * <p>
 * - avaje-http generates the adapter for the {@code @Controller}
 * - avaje-inject generates dependency injection wiring
 * - avaje-config reads external configuration (application.properties|yaml, application-test.properties|yaml).
 */
public interface BootJex {

  /**
   * Start Jex server using {@code @Controller} with avaje-inject, avaje-http, avaje-config.
   *
   * <pre>{@code
   *   public static void main(String[] args) {
   *
   *     BootJex.start();
   *   }
   * }</pre>
   */
  static void start() {
    BootJexState.start();
  }
}

Add support for component test with .. @Inject of Http client starts server, creates client (for injection)

Example, @Inject HttpClientContext client

  • The server is started on a random port
  • The client is created using the port and injected into the test
  • At test completion the server is stopped
@InjectTest
class HelloControllerTest {

  @Inject HttpClientContext client;

  @Test
  void hello() {
    HttpResponse<String> hello = client.request().path("hello")
      .GET()
      .asString();

    assertThat(hello.statusCode()).isEqualTo(200);

  }
}

Example

  • Given HelloApi is a java interface annotated with @Client + @Get, @Post etc ...
  • A static field is used ... The client and server is run once and used for all the tests in the class
  • The server is started on a random port (for the class)
  • The client is created using the port and injected into the test (for the class, static field)
  • All tests run
  • At completion the server is stopped
import io.avaje.inject.test.InjectTest;
import jakarta.inject.Inject;
import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

@InjectTest
class HelloController2Test {

  @Inject static HelloApi client;

  @Test
  void hello() {
    String hi = client.hi();
    assertThat(hi).isEqualTo("hisay+yo");
  }

  @Test
  void hello2() {
    String hi = client.hi();
    assertThat(hi).isEqualTo("hisay+yo");
  }

}

[Enhancement] Support HTTP/3

https://www.eclipse.org/jetty/documentation/jetty-11/programming-guide/index.html#pg-server-http-connector-protocol-http3
Jetty has a full implementation of HTTP3 (the only other implementation I have seen since flupke).

Motivation

  • Better performance (difference would be negligible right now, but once the specification has been fully standardized, it will be many times better than HTTP/2, and HTTP3 is already being used to improve performance of sites with Cloudflare, and by e.g. Google in their core products to improve responsiveness)
  • On the road to supporting WebTransport as well (nobody has made a proper implementation of WebTransport in any language except Go, but for QUIC, kwik exists, which flupke uses as well)
    • WebTransport will boost the performance of WebSockets by using QUIC as well, just like HTTP/3 is (HTTP/3 has other reasons to boost performance as well).
    • WebTransport will finally rid people of the suffering of WebRTC, and allow for UDP data streaming for e.g. audio packets, game movement, etc, or for anything that requires this unsafe data streaming (and this will boost performance as well by increasing sheer throughput by not having the behemoth of dependencies on our backends, we could finally have the four wishes in our fever dreams of encryption, congestion control, CORS/consent and a damn simple specification).

Drawbacks

  • HTTP/3 has limited support, being majorly supported by Chrome (87+ on desktop, 111+ on Android) & Firefox (88+ on desktop, 110+ on Android), but with zero support from Safari (by extension, zero iOS support). While we could theoretically do the approach documented by Jetty with the alternate service header, I have mixed opinions about making this "temporary" solution a default rather than enforcing first-class support for HTTP/3 on peoples' sites; you can see how on the Cloudflare Quic test, your first connection ends up always being a HTTP/2 one before your client caches the support for HTTP/3. All supporting browsers support this header by default so this does work as a solution nontheless.
  • WebTransport (not included with this issue but again, for the future? Jex doesn't even have WebSockets yet...) is even less supported working only on Chrome (97+ on desktop, 111+ on Android); no other browsers support it.
  • Is there demand for this outside of me?

Jetty 11.0.1 fails test with 400 - Ambiguous segment in URI (when this was previously 200)

Refer jetty/jetty.project#6001

For jetty-10 and beyond, the default is changed to disallow all three. It is now configurable in a new UriCompliance class that can be set on HttpConfiguration

// RouteSplatTest

  @Test
  void when_utf8Encoded() {
    String path = URLEncoder.encode("java/kotlin", StandardCharsets.UTF_8)
      + "/two/" + URLEncoder.encode("x/y", StandardCharsets.UTF_8);

    HttpResponse<String> res = pair.request().path(path).get().asString();

    assertThat(res.body()).isEqualTo("splats:[java/kotlin, x/y]");
    assertThat(res.statusCode()).isEqualTo(200);
  }

Add support for splat / wildcard path parameters

    var app = Jex.create()
      .routing(routing -> routing
        .get("/*/one", ctx -> ctx.text("splat:" + ctx.splat(0)))
        .get("/*/two/*", ctx -> ctx.text("splats:" + ctx.splat(0) +" and " + ctx.splat(1)))
        .get("/*/two/*", ctx -> ctx.text("splats:" + ctx.splats()))
      );

Support application roles per endpoint

1. Create an app specific enum that implements Role

import io.avaje.jex.Role;

/**
 * Create an App specific enum that implements Role.
 */
public enum AppRoles implements Role {
  ADMIN,
  USER
}

2. Create an Roles enum that uses the app specific enum (for use with avaje-http controllers)

import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
 * Create an app specific Role annotation that uses the
 * app specific role enum.
 */
@Target(value={METHOD, TYPE})
@Retention(value=RUNTIME)
public @interface Roles {

  /**
   * Specify the permitted roles (using app specific enum).
   */
  AppRoles[] value() default {};
}

3. Use the Role enum on endpoints that we want the user roles check

      .routing(routing -> routing
        .get(ctx -> ctx.text("get"))
        .get("/multi", ctx -> ... ).withRoles(AppRoles.ADMIN, AppRoles.USER)
        .get("/user", ctx -> ... ).withRoles(AppRoles.USER)
      );

4. Implement and register the AccessManager

.accessManager((handler, ctx, permittedRoles) -> {
        final String role = ctx.queryParam("role");
        if (role == null || !permittedRoles.contains(AppRoles.valueOf(role))) {
          ctx.status(401).text("Unauthorized");
        } else {
          ctx.attribute("authBy", role);
          handler.handle(ctx);
        }
      })

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.