Skip to content

Commit

Permalink
servlet
Browse files Browse the repository at this point in the history
  • Loading branch information
oxsean committed Jun 14, 2024
1 parent e4fa369 commit e42a5d7
Show file tree
Hide file tree
Showing 12 changed files with 481 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ spring:
dubbo:
application:
name: ${spring.application.name}
qos-enable: false
protocol:
name: dubbo
port: -1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,17 @@
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-triple-servlet</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,14 @@
package org.apache.dubbo.springboot.demo.provider;

import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.apache.dubbo.rpc.protocol.tri.servlet.TripleFilter;

import java.util.concurrent.CountDownLatch;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
@EnableDubbo(scanBasePackages = {"org.apache.dubbo.springboot.demo.provider"})
Expand All @@ -31,4 +34,12 @@ public static void main(String[] args) throws Exception {
System.out.println("dubbo service started");
new CountDownLatch(1).await();
}

@Bean
public FilterRegistrationBean<TripleFilter> tripleFilter() {
FilterRegistrationBean<TripleFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new TripleFilter());
registrationBean.addUrlPatterns("/*");
return registrationBean;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ dubbo:
application:
name: ${spring.application.name}
protocol:
name: dubbo
port: -1
name: tri
port: 8081
registry:
id: zk-registry
address: zookeeper://127.0.0.1:2181
Expand All @@ -41,3 +41,10 @@ dubbo:
exporter:
enabled: true
enable-metadata: true

server:
port: 8081
http2:
enabled: true
tomcat:
keep-alive-timeout: 180000
58 changes: 58 additions & 0 deletions dubbo-plugin/dubbo-triple-servlet/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-plugin</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>dubbo-triple-servlet</artifactId>

<properties>
<servlet4_version>4.0.1</servlet4_version>
</properties>

<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-triple</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet4_version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-remoting-netty4</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-remoting-http12</artifactId>
<version>${project.version}</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.protocol.tri.servlet;

import org.apache.dubbo.remoting.http12.HttpHeaders;
import org.apache.dubbo.remoting.http12.h2.Http2Header;

import javax.servlet.http.HttpServletRequest;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

final class HttpMetadataAdapter implements Http2Header {

private final HttpServletRequest request;

private HttpHeaders headers;

HttpMetadataAdapter(HttpServletRequest request) {
this.request = request;
}

@Override
public HttpHeaders headers() {
HttpHeaders headers = this.headers;
if (headers == null) {
headers = new HttpHeaders();
Enumeration<String> en = request.getHeaderNames();
while (en.hasMoreElements()) {
String key = en.nextElement();
List<String> values = new ArrayList<>(1);
Enumeration<String> ven = request.getHeaders(key);
while (ven.hasMoreElements()) {
values.add(ven.nextElement());
}
headers.put(key, values);
}
this.headers = headers;
}
return headers;
}

@Override
public String method() {
return request.getMethod();
}

@Override
public String path() {
String query = request.getQueryString();
return query == null ? request.getRequestURI() : request.getRequestURI() + '?' + query;
}

@Override
public String status() {
return null;
}

@Override
public int id() {
return -1;
}

@Override
public boolean isEndStream() {
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.protocol.tri.servlet;

import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.remoting.http12.HttpHeaderNames;
import org.apache.dubbo.remoting.http12.HttpHeaders;
import org.apache.dubbo.remoting.http12.HttpMetadata;
import org.apache.dubbo.remoting.http12.HttpOutputMessage;
import org.apache.dubbo.remoting.http12.h2.H2StreamChannel;
import org.apache.dubbo.remoting.http12.h2.Http2Header;
import org.apache.dubbo.remoting.http12.h2.Http2OutputMessage;
import org.apache.dubbo.remoting.http12.h2.Http2OutputMessageFrame;

import javax.servlet.AsyncContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.CompletableFuture;

final class ServletStreamChannel implements H2StreamChannel {

private static final Logger LOG = LoggerFactory.getLogger(ServletStreamChannel.class);

private final HttpServletRequest request;
private final HttpServletResponse response;
private final AsyncContext context;

ServletStreamChannel(HttpServletRequest request, HttpServletResponse response, AsyncContext context) {
this.request = request;
this.response = response;
this.context = context;
}

@Override
public CompletableFuture<Void> writeResetFrame(long errorCode) {
try {
response.getOutputStream().close();
} catch (Throwable t) {
LOG.error("Failed to close response output stream", t);
} finally {
context.complete();
}
return CompletableFuture.completedFuture(null);
}

@Override
public Http2OutputMessage newOutputMessage(boolean endStream) {
return new Http2OutputMessageFrame(new ByteArrayOutputStream(256), endStream);
}

@Override
public CompletableFuture<Void> writeHeader(HttpMetadata httpMetadata) {
boolean endStream = ((Http2Header) httpMetadata).isEndStream();
try {
HttpHeaders headers = httpMetadata.headers();
if (endStream) {
response.setTrailerFields(() -> {
Map<String, String> map = new HashMap<>();
for (Entry<String, List<String>> entry : headers.entrySet()) {
map.put(entry.getKey(), entry.getValue().get(0));
}
return map;
});
} else {
for (Entry<String, List<String>> entry : headers.entrySet()) {
String key = entry.getKey();
List<String> values = entry.getValue();
if (HttpHeaderNames.STATUS.getName().equals(key)) {
response.setStatus(Integer.parseInt(values.get(0)));
continue;
}
if (values.size() == 1) {
response.setHeader(key, values.get(0));
} else {
for (int i = 0, size = values.size(); i < size; i++) {
response.addHeader(key, values.get(i));
}
}
}
}
} catch (Throwable t) {
LOG.error("Failed to write header", t);
} finally {
if (endStream) {
context.complete();
}
}
return CompletableFuture.completedFuture(null);
}

@Override
public CompletableFuture<Void> writeMessage(HttpOutputMessage httpOutputMessage) {
OutputStream body = httpOutputMessage.getBody();
try {
ServletOutputStream out = response.getOutputStream();
((ByteArrayOutputStream) body).writeTo(out);
out.flush();
} catch (Throwable t) {
LOG.error("Failed to write message", t);
} finally {
if (((Http2OutputMessage) httpOutputMessage).isEndStream()) {
context.complete();
}
}
return CompletableFuture.completedFuture(null);
}

@Override
public SocketAddress remoteAddress() {
return InetSocketAddress.createUnresolved(request.getRemoteAddr(), request.getRemotePort());
}

@Override
public SocketAddress localAddress() {
return InetSocketAddress.createUnresolved(request.getLocalAddr(), request.getLocalPort());
}

@Override
public void flush() {}
}
Loading

0 comments on commit e42a5d7

Please sign in to comment.