- Saved searches
- Use saved searches to filter your results more quickly
- License
- FusionAuth/java-http
- Name already in use
- Sign In Required
- Launching GitHub Desktop
- Launching GitHub Desktop
- Launching Xcode
- Launching Visual Studio Code
- Latest commit
- Git stats
- Files
- README.md
- About
- Простой HTTP-сервер на Java
- HTTPServer
- Очередь выполнения запросов
- Код сервера
- HTTPHandler
- «). append(«Hello «) .append(requestParamValue) .append(«
Saved searches
Use saved searches to filter your results more quickly
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.
A full featured, stand-alone, high-performance HTTP server and client written entirely in plain Java
License
FusionAuth/java-http
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Sign In Required
Please sign in to use Codespaces.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching Xcode
If nothing happens, download Xcode and try again.
Launching Visual Studio Code
Your codespace will open once ready.
There was a problem preparing your codespace, please try again.
Latest commit
Git stats
Files
Failed to load latest commit information.
README.md
FusionAuth HTTP client and server
NOTE: This project is in progress.
The goal of this project is to build a full-featured HTTP server and client in plain Java without the use of any libraries. The client and server will use non-blocking NIO in order to provide the highest performance possible.
To add this library to your project, you can include this dependency in your Maven POM:
dependency> groupId>io.fusionauthgroupId> artifactId>java-httpartifactId> version>0.1.15version> dependency>
If you are using Gradle, you can add this to your build file:
implementation 'io.fusionauth:java-http:0.1.15'
If you are using Savant, you can add this to your build file:
dependency(id: "io.fusionauth:java-http:0.1.15")
Creating a server is simple:
import io.fusionauth.http.server.HTTPListenerConfiguration; import io.fusionauth.http.server.HTTPServer; import io.fusionauth.http.server.HTTPHandler; public class Example < public static void main(String. args) < HTTPHandler handler = (req, res) -> < // Handler code goes here >; HTTPServer server = new HTTPServer().withHandler(handler).withListener(new HTTPListenerConfiguration(4242)); server.start(); // Use server server.close(); > >
Since the HTTPServer class implements java.io.Closeable , you can also use a try-resource block like this:
import io.fusionauth.http.server.HTTPListenerConfiguration; import io.fusionauth.http.server.HTTPServer; import io.fusionauth.http.server.HTTPHandler; public class Example < public static void main(String. args) < HTTPHandler handler = (req, res) -> < // Handler code goes here >; try (HTTPServer server = new HTTPServer().withHandler(handler).withListener(new HTTPListenerConfiguration(4242))) < server.start(); // When this block exits, the server will be shutdown > > >
You can also set various options on the server using the with methods on the class like this:
import java.time.Duration; import io.fusionauth.http.server.HTTPListenerConfiguration; import io.fusionauth.http.server.HTTPServer; import io.fusionauth.http.server.HTTPHandler; public class Example < public static void main(String. args) < HTTPHandler handler = (req, res) -> < // Handler code goes here >; HTTPServer server = new HTTPServer().withHandler(handler) .withNumberOfWorkerThreads(42) .withShutdownDuration(Duration.ofSeconds(10L)) .withListener(new HTTPListenerConfiguration(4242)); server.start(); // Use server server.close(); > >
The HTTP server implements TLS 1.0-1.3 using the Java SSLEngine. To enable TLS for your server, you need to create an HTTPListenerConfiguration that includes a certificate and private key. Most production use-cases will use a proxy such as Apache, Nginx, ALBs, etc. In development, it is recommended that you set up self-signed certificates and load those into the HTTP server.
To set up self-signed certificates on macOS, you can use the program mkcert . Here is an example:
brew install mkcert mkcert -install mkdir -p ~/dev/certificates mkcert -cert-file ~/dev/certificates/example.org.pem -key-file ~/dev/certificates/example.org.key example.org
In production environments, your certificate will likely be signed by one or more intermediate Certificate Authorities. In addition to the server certificate, ensure that all intermediate CA certificates in the chain are included in your pem file.
Now you can load these into the HTTP server like this:
import java.nio.file.Files; import java.nio.file.Paths; import java.time.Duration; import io.fusionauth.http.server.HTTPHandler; import io.fusionauth.http.server.HTTPServer; public class Example < private String certificate; private String privateKey; public static void main(String[] args) < String homeDir = System.getProperty("user.home"); certificate = Files.readString(Paths.get(homeDir + "/dev/certificates/example.org.pem")); privateKey = Files.readString(Paths.get(homeDir + "/dev/certificates/example.org.key")); HTTPHandler handler = (req, res) -> < // Handler code goes here >; HTTPServer server = new HTTPServer().withHandler(handler) .withListener(new HTTPListenerConfiguration(4242, certificate, privateKey)); // Use server server.close(); > >
And finally, you’ll need to add the domain name to your hosts file to ensure that the SNI lookup handles the certificate correctly. For this example, you would use this entry in the /etc/hosts file:
Then you can open https://example.org in a browser or call it using an HTTP client (i.e. Insomnia, Postman, etc or in code).
A key component for this project is to have awesome performance. Here are some basic metrics using the FusionAuth load test suite against a simple application using the Prime Framework MVC. The controller does nothing except return a simple 200. Here are some simple comparisons between Tomcat , Netty , and java-http .
The load test configuration is set to 10 clients with 500,000 requests each. The client is Restify which is a FusionAuth library that uses HttpURLConnection under the hoods. All the servers were HTTP so that TLS would not introduce any additional latency.
Here are the current test results:
Server | RPS | Failures per second |
---|---|---|
java-http | 63,216 | 0 |
Tomcat | 51,351 | 0.103 |
Netty | 540 | 1.818 |
Netty and Tomcat both seem to suffer from buffering and connection issues at very high scale. Regardless of the configuration, both servers always begins to fail with connection timeout problems at scale. java-http does not have these issues because of the way it handles connections via the selector. Connections don’t back up and client connection pools can always be re-used with Keep-Alive.
The general requirements and roadmap are as follows:
- Basic HTTP 1.1
- Support Keep-Alive
- Support Expect-Continue 100
- Support chunked request
- Support chunked response
- Support streaming entity bodies (via chunking likely)
- Support compression (default and per response options)
- Support cookies in request and response
- Clean up HTTPRequest
- Support form data
- Support multipart form data
- Support TLS
- Support trailers
- Support HTTP 2
- Basic HTTP 1.1
- Support Keep-Alive
- Support TLS
- Support Expect-Continue 100
- Support chunked request and response
- Support streaming entity bodies
- Support form data
- Support multipart form data
- Support HTTP 2
Project Loom is an exciting development which brings a lot of great new features to Java, such as fibers, continuations and more.
Loom is currently available in Java 19 as a preview feature. Therefore, you can’t use it without compiled code that is difficult to use in future Java releases.
This project is anchored to the Java LTS releases to ensure compatibility. Loom will be evaluated once it is out of preview, and available in an LTS version of Java.
The next scheduled LTS release will be Java 21 set to release in September 2023. We are looking forward to that release and to see if we can leverage the Loom features in this project.
We are looking for Java developers that are interested in helping us build the client and server. If you know a ton about networks and protocols and love writing clean, high-performance Java, contact us at dev@fusionauth.io.
Note: This project uses the Savant build tool. To compile using Savant, follow these instructions:
$ mkdir ~/savant $ cd ~/savant $ wget http://savant.inversoft.org/org/savantbuild/savant-core/2.0.0-RC.6/savant-2.0.0-RC.6.tar.gz $ tar xvfz savant-2.0.0-RC.6.tar.gz $ ln -s ./savant-2.0.0-RC.6 current $ export PATH=$PATH:~/savant/current/bin/
About
A full featured, stand-alone, high-performance HTTP server and client written entirely in plain Java
Простой HTTP-сервер на Java
Вы хотите реализовать HTTP-сервер , но не хотите рисковать написанием полноценного HTTP-сервера? Разработка HTTP-сервера с полной функциональностью не является тривиальной задачей. Но у Java есть решение этой проблемы. Java поддерживает встроенный HTTP-сервер. Просто написав 100 строк кода, мы можем разработать несколько приличный HTTP-сервер, который может обрабатывать запросы. Мы также можем использовать его для обработки других HTTP-команд.
HTTPServer
Java SDK предоставляет встроенный сервер под названием HttpServer . Этот класс относится к пакету com.sun.net .
Мы можем создать экземпляр сервера следующим образом:
HttpServer server = HttpServer.create(new InetSocketAddress("localhost", 8001), 0);
Приведенная выше строка создает экземпляр HTTPServer на локальном узле с номером порта 8001. Но есть еще один аргумент со значением 0. Это значение используется для обратной регистрации .
Очередь выполнения запросов
Когда сервер принимает запрос клиента, этот запрос сначала будет поставлен в очередь операционной системой. Позже он будет передан на сервер для обработки запроса. Все эти одновременные запросы будут поставлены в очередь операционной системой. Однако операционная система сама решит, сколько из этих запросов может быть поставлено в очередь в любой данный момент времени. Это значение представляет обратную регистрацию. В нашем примере это значение равно 0, что означает, что мы не ставим в очередь никаких запросов.
Код сервера
Мы собираемся разработать следующий HTTP-сервер:
server.createContext("/test", new MyHttpHandler()); server.setExecutor(threadPoolExecutor); server.start(); logger.info(" Server started on port 8001");
Мы создали контекст под названием test . Это не что иное, как корень контекста приложения. Второй параметр — это экземпляр обработчика, который будет обрабатывать HTTP-запросы. Мы рассмотрим этот класс в ближайшее время.
Мы можем использовать исполнителя пула потоков вместе с этим экземпляром сервера. В нашем случае мы создали пул из 10 потоков.
ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor)Executors.newFixedThreadPool(10);
С помощью всего трех-четырех строк кода мы создали HTTP-сервер с корневым контекстом, который прослушивает порт!
HTTPHandler
Это интерфейс с вызванным методом handle(..) . Давайте посмотрим на нашу реализацию этого интерфейса.