Vert.x 内核模块 编写HTTP服务器(六【1】)
来源:互联网 发布:淘宝店铺店招设计 编辑:程序博客网 时间:2024/05/16 17:01
编写HTTP服务器与客户端
Vert.x使编写非阻塞的HTTP客户端和服务器更加容易。Vert.x支持HTTP/1.0,HTTP/1.1,HTTP/2等协议。HTTP基本的API与HTTP/1.x和HTTP/2是相同的,为了处理HTTP/2协义需要获取特殊的API。
创建HTTP服务器
使用默认的配置创建HTTP服务器是最简单的方法:
HttpServer server = vertx.createHttpServer();
配置HTTP服务器
如果不期望使用默认配置,可以在创建服务器时传入HttpServerOptions实例进行配置:
HttpServerOptions options = newHttpServerOptions().setMaxWebsocketFrameSize(1000000);
HttpServer server =vertx.createHttpServer(options);
配置HTTP/2服务器
· 在通过应用层协义协商(ALPN)的TLS协商时使用,h2用来标识HTTP/2协议
· 在TCP使用清晰文本,h2c标识HTTP/2协议,例如通过升级HTTP/1.1升级请求或直接建立的连接。
为了处理h2请求,TLS必须启用并同setUseAlpn一起用:
HttpServerOptions options = newHttpServerOptions()
.setUseAlpn(true)
.setSsl(true)
.setKeyStoreOptions(newJksOptions().setPath("/path/to/my/keystore"));
HttpServer server = vertx.createHttpServer(options);
ALPN是TLS扩展,在客户端和服务器开始交互数据之前进行协议协商。不支持ALPN的客户端一直使用经典的SSL进行握手。如果服务器或客户端决定这样,ALPN一般同h2协议达成一致,尽管可以使用HTTP/1.1。
为了处理h2c请求,TLS必须被禁用,如果想升级到HTTP/2,服务器将HTTP/1.2请求升级到HTTP/2。这将直接接收以PRI *HTTP/2.0\r\nSM\r\n开头的h2c请求。
警示:大多数浏览器不支持h2c,所以对外服务的网站,应该用h2而不是h2c
在服务器接收一个http/2连接时,服务器将向客户端发送它的初始设置(initial settings).这些设置对怎样使用连接进行定义,默认的服务器初始设置如下:
· getMaxConcurrentStreams: 100 作为HTTP/2推荐
· 其他默认的HTTP/2设置值
记录网络服务器行为
为了调试目的,可以记录网络行为
HttpServerOptions options = newHttpServerOptions().setLogActivity(true);
HttpServer server =vertx.createHttpServer(options)
参看记录网络行为章节获取详细说明。
开始服务器侦听
为了让服务器开始监听到来的请求,必需使用一个listen方法。为了告诉服务器在哪个网口那个端口侦听,可以使用配置选项。
HttpServer server = vertx.createHttpServer();
server.listen();
或者在调用listen方法时指定主机与端口,那么不配置时使用什么选项.
HttpServer server = vertx.createHttpServer();
server.listen(8080, "myhost.com");
默认的主机是0.0.0.0,这意味着侦听所有可用的网址,默认端口为80. 因为实际绑定是异步的,所以在调用listen方法返回时可能并没有完成侦听。如果想获取服务器实际侦听完成的通知,可以在listen方法中添加一个处理器。下面是一个例子:
HttpServer server = vertx.createHttpServer();
server.listen(8080, "myhost.com", res-> {
if(res.succeeded()) {
System.out.println("Server is now listening!");
} else{
System.out.println("Failed to bind!");
}
});
获取进行请求的通知
在请求到达时需要设置请求处理器(requestHandler),获取通知:
HttpServer server = vertx.createHttpServer();
server.requestHandler(request -> {
//Handle the request in here
});
处理请求
当一个请求到达,将会传一个HttpServerRequest的实例到请求处理器并调用请求处理器。这个对象代表了服务器端HTTP请求。在请求头全部被读取时,处理器会被调用。如果一个请求有请求体,这个请求体将会在请求处理器调用后某个进间到达服务器。
可以从服务器端请求对象中获取uri,path,params和头信息,和其他信息。每个服务器请求对象与一个服务响应对象关联。你使用response获取HttpServerResponse对象的引用。这里有一个服务器端处理请求并响应“hello world”到客端的例子。
vertx.createHttpServer().requestHandler(request-> {
request.response().end("Hello world");
}).listen(8080);
请求版本
在HTTP请求中可以获取HTTP特定版本version
请求的方法
使用method获取请求中的方法(如是否是GET,POST,PUT,DELETE,HEAD,OPTIONS,etc)
请求URI
使用uri获取请求的URI.注意,这是一个实际传入HTTP请求的URI,并总是相对的URI。URI在HTTP规范-请求-URI节进行定义。
请求路径
使用 path可以获取URI中的path部分,
例如,如果请求的URI是:
a/b/c/page.html?param1=abc¶m2=xyz
然后中径是
/a/b/c/page.html
请求查询
用query 返回URI中的query部分
如果请求的URI是:
a/b/c/page.html?param1=abc¶m2=xyz
Query是:
param1=abc¶m2=xyz
请求头
用header方法返回HTTP请求中的头。Header方法返回一个MultiMap实例,MultiMap类似通用的Map或者Hash,只是一个KEY可以有多个值,这是因为HTTP允许同一个头的KEY可以有多个值。Header的KEY大小写敏感:
MultiMap headers = request.headers();
// Get the User-Agent:
System.out.println("User agent is " +headers.get("user-agent"));
// You can also do this and get the sameresult:
System.out.println("User agent is " +headers.get("User-Agent"));
请求主机
用host方法获取请求的主机。对于HTTP/1.x 请求中的host头被返回,对HTTP/1请求:authority的假头被返回。
请求参数
用params返回请求中的参数。与headers返回的MultiMap实例类似,因为一个名称可以参数可以有多个值。请求参数通过请求URI发送给服务器,紧随路径。例如:
/page.html?param1=abc¶m2=xyz
包含的参数如下:
param1: 'abc'
param2: 'xyz
请求参数可以从请求的URL中获取。如果有表单属性作为HTML表单任务提交到multi-part/form-data请求,而这些属性将不会出现在params中。
远程地址
请求发送者的地址,通过remoteAddress获取。
绝对URI
传入到HTTP请求中的URI一般是相对地址。如果你想获取响应的绝对URI,使用absoluteURI.
结束处理器
在整个请求包括请求体被完全读取,endHandler将被调用。
从请求体中读取数据
一般情况下HTTP请包含我们需要读取的请求体。如前所述,在请求头到达时,请处理器被调用,所以在那个点请求对象并不包含请求体。
这是因为请求体可能比较大(如文件上传),通常我们在处理前并不想在内存缓存整个请求体,如果那样,服务器内存资源可以会被耗尽。
为了获取体,可以在请求上添加处理器,这样每当有请求体的数据块到达时,处理器就会被调用。下面是一个例子:
request.handler(buffer -> {
System.out.println("I have received a chunk of the body of length" + buffer.length());
});
传给处理器的参数是Buffer,处理可以被多次调用,这取决于请求体的大小。
一些情况下(请求体很小),可以将集所有的请求体缓存在内存中,所以可象下面一样组合:
Buffer totalBuffer = Buffer.buffer();
request.handler(buffer -> {
System.out.println("I have received a chunk of the body of length" + buffer.length());
totalBuffer.appendBuffer(buffer);
});
request.endHandler(v -> {
System.out.println("Full body received, length = " +totalBuffer.length());
});
这是一个常用的例子,Vert.x提供了一个bodyHandler为你处理。在所有请求体到达后,请求体处理器执行一次。
request.bodyHandler(totalBuffer -> {
System.out.println("Full body received, length = " +totalBuffer.length());
});
泵接请求
请求对象是一个读数据流(ReadStream),所以可以将期泵接到写数据流实例 (WriteStream).参看流与泵章节获取详细说明。
处理HTML表单
HTML表达可使用application/x-www-form-rlencoded 或者 multipart/form-data的内空类别进行提交。
对于URL编码的表单,表单的属性会编码进URL,与查询参数类似。
对于多部分表单,表单属性被编码时请求体,直到所有的请求体被从线上读取,才能得到。
多部分表单可以包含文件上传。
如果你想获取多部分表单的属性,在任何请求体被读取前,应该告知Vert.x期望收到这样的表单,通过设置setExpectMultipart为true设置告知,然就可以在整个请求体读取完成后,通过formAttributes获取表单的实际属性。
server.requestHandler(request -> {
request.setExpectMultipart(true);
request.endHandler(v -> {
//The body has now been fully read, so retrieve the form attributes
MultiMap formAttributes = request.formAttributes();
});
});
处理表单上传文件
Vert.x通过编码进行multi-part请求体,进行文件上传。为了获取上传文件,必须设置Vert.x获取multi-part表单并在请设置uploadHandler处理上传文件。上传处理器在每个上传对象到达服务器时被调用。HttpServerFileUpload实例作为上传处理器参数。
server.requestHandler(request -> {
request.setExpectMultipart(true);
request.uploadHandler(upload -> {
System.out.println("Got a file upload " + upload.name());
});
});
文件上传可以大到我们不能在一个缓存中提供整个上传实体,如果缓存整个上传实体可能会耗尽服务器内存,所以以数据块的方式接收上传数据。
request.uploadHandler(upload -> {
upload.handler(chunk -> {
System.out.println("Received a chunk of the upload of length "+ chunk.length());
});
});
上传对象是一个读取流,所以可以泵接请求体到任意的写数据流实例。参看流和泵接章节获取详细说明。
如果想上传文件到磁盘的某个地方,请使用streamToFileSystem:
request.uploadHandler(upload -> {
upload.streamToFileSystem("myuploads_directory/" +upload.filename());
});
警示:在生产系统中必须确定检查文件名,避免恶意客户端上传文件到你的文件系统的任意地方,参看安全注释获取更多信息。- Vert.x 内核模块 编写HTTP服务器(六【1】)
- Vert.x 内核模块 编写HTTP服务器(七【2】)
- Vert.x 内核模块 编写HTTP服务器(八【3】)
- Vert.x Web模块(六)
- Vert.x 内核模块 Buffer( 四 )
- Vert.x内核模块 结束
- Vert.x 核心模块 编写TCP服务器端(五)
- Vert.x 核心模块 内核组件Verticle(二)
- Vert.x 内核模块 集群管理(十八)
- Vert.x核心模块 HTTP客户端推送 (九【4】)
- Vert.x核心模块 HTTP客户端推送 (十【5】)
- Vert.x 核心模块 HTTP websocket(十一【6】)
- Vert.x内核模块 内核组件 EventBus (三)
- Vert.x 核心模块 DNS(十五)
- Vert.x核心模块(十七) 命令行
- Vert.x Web 模块(一)
- Vert.x Web模块(二)
- Vert.x Web模块(三)
- eclipse自动提示
- 设计模式学习(九)————模板方法模式
- 2016年四季度公开课安排
- $(document).ready(document_onReady);
- leetcode求和题目
- Vert.x 内核模块 编写HTTP服务器(六【1】)
- mouseover与mouseenter,mouseout与mouseleave的区别及用法
- 使用AlarmManager实现精确定时任务
- /etc/ld.so.conf.d/目录下文件的作用
- Android开源项目第四篇——开发及测试工具篇
- CodeChef2016年09月问题
- JS判断当前是否为移动设备的浏览器
- centos7 64位编译hadoop源码
- AndroidStudio 从基本到高级使用技巧