@@ -27,6 +27,7 @@ | |||
<module>sentinel-spring-cloud-gateway-adapter</module> | |||
<module>sentinel-spring-webmvc-adapter</module> | |||
<module>sentinel-zuul2-adapter</module> | |||
<module>sentinel-okhttp-adapter</module> | |||
<module>sentinel-jax-rs-adapter</module> | |||
</modules> | |||
@@ -0,0 +1,63 @@ | |||
# Sentinel OkHttp Adapter | |||
## Introduction | |||
Sentinel provides integration for OkHttp client to enable flow control for web requests. | |||
Add the following dependency in `pom.xml` (if you are using Maven): | |||
```xml | |||
<dependency> | |||
<groupId>com.alibaba.csp</groupId> | |||
<artifactId>sentinel-okhttp-adapter</artifactId> | |||
<version>x.y.z</version> | |||
</dependency> | |||
``` | |||
We can add the `SentinelOkHttpInterceptor` interceptor when `OkHttpClient` at initialization, for example: | |||
```java | |||
OkHttpClient client = new OkHttpClient.Builder() | |||
.addInterceptor(new SentinelOkHttpInterceptor()) | |||
.build(); | |||
``` | |||
## Configuration | |||
- `SentinelOkHttpConfig` configuration: | |||
| name | description | type | default value | | |||
|------|------------|------|-------| | |||
| extractor | custom resource extractor | `OkHttpResourceExtractor` | `DefaultOkHttpResourceExtractor` | | |||
| fallback | handle request when it is blocked | `OkHttpFallback` | `DefaultOkHttpFallback` | | |||
### extractor (resource extractor) | |||
We can define `OkHttpResourceExtractor` to custom resource extractor replace `DefaultOkHttpResourceExtractor`, for example: okhttp:GET:ip:port/okhttp/back/1 ==> /okhttp/back/{id} | |||
```java | |||
OkHttpResourceExtractor extractor = (request, connection) -> { | |||
String resource = request.url().toString(); | |||
String regex = "/okhttp/back/"; | |||
if (resource.contains(regex)) { | |||
resource = resource.substring(0, resource.indexOf(regex) + regex.length()) + "{id}"; | |||
} | |||
return resource; | |||
}; | |||
SentinelOkHttpConfig.setExtractor(extractor); | |||
``` | |||
### fallback (Block handling) | |||
We can define `OkHttpFallback` to handle request is blocked according to the actual scenario, for example: | |||
```java | |||
public class DefaultOkHttpFallback implements OkHttpFallback { | |||
@Override | |||
public Response handle(Request request, Connection connection, BlockException e) { | |||
// Just wrap and throw the exception. | |||
throw new SentinelRpcException(e); | |||
} | |||
} | |||
``` |
@@ -0,0 +1,68 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<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"> | |||
<parent> | |||
<artifactId>sentinel-adapter</artifactId> | |||
<groupId>com.alibaba.csp</groupId> | |||
<version>1.8.0-SNAPSHOT</version> | |||
</parent> | |||
<modelVersion>4.0.0</modelVersion> | |||
<artifactId>sentinel-okhttp-adapter</artifactId> | |||
<packaging>jar</packaging> | |||
<properties> | |||
<okhttp.version>3.6.0</okhttp.version> | |||
<spring.boot.version>2.1.3.RELEASE</spring.boot.version> | |||
<spring-test.version>5.1.5.RELEASE</spring-test.version> | |||
</properties> | |||
<dependencies> | |||
<dependency> | |||
<groupId>com.alibaba.csp</groupId> | |||
<artifactId>sentinel-core</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.squareup.okhttp3</groupId> | |||
<artifactId>okhttp</artifactId> | |||
<version>${okhttp.version}</version> | |||
<scope>provided</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>junit</groupId> | |||
<artifactId>junit</artifactId> | |||
<scope>test</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.mockito</groupId> | |||
<artifactId>mockito-core</artifactId> | |||
<scope>test</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.alibaba</groupId> | |||
<artifactId>fastjson</artifactId> | |||
<scope>test</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-starter-web</artifactId> | |||
<version>${spring.boot.version}</version> | |||
<scope>test</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-test</artifactId> | |||
<version>${spring.boot.version}</version> | |||
<scope>test</scope> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.springframework</groupId> | |||
<artifactId>spring-test</artifactId> | |||
<version>${spring-test.version}</version> | |||
<scope>test</scope> | |||
</dependency> | |||
</dependencies> | |||
</project> |
@@ -0,0 +1,55 @@ | |||
/* | |||
* Copyright 1999-2020 Alibaba Group Holding Ltd. | |||
* | |||
* Licensed 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 com.alibaba.csp.sentinel.adapter.okhttp; | |||
import com.alibaba.csp.sentinel.*; | |||
import com.alibaba.csp.sentinel.adapter.okhttp.config.SentinelOkHttpConfig; | |||
import com.alibaba.csp.sentinel.slots.block.BlockException; | |||
import com.alibaba.csp.sentinel.util.StringUtil; | |||
import okhttp3.Interceptor; | |||
import okhttp3.Request; | |||
import okhttp3.Response; | |||
import java.io.IOException; | |||
/** | |||
* @author zhaoyuguang | |||
*/ | |||
public class SentinelOkHttpInterceptor implements Interceptor { | |||
@Override | |||
public Response intercept(Chain chain) throws IOException { | |||
Entry entry = null; | |||
try { | |||
Request request = chain.request(); | |||
String name = SentinelOkHttpConfig.getExtractor().extract(request.url().toString(), request, chain.connection()); | |||
if (!StringUtil.isEmpty(SentinelOkHttpConfig.getPrefix())) { | |||
name = SentinelOkHttpConfig.getPrefix() + name; | |||
} | |||
entry = SphU.entry(name, ResourceTypeConstants.COMMON_WEB, EntryType.OUT); | |||
return chain.proceed(request); | |||
} catch (BlockException e) { | |||
return SentinelOkHttpConfig.getFallback().handle(chain.request(), chain.connection(), e); | |||
} catch (Throwable t) { | |||
Tracer.traceEntry(t, entry); | |||
throw t; | |||
} finally { | |||
if (entry != null) { | |||
entry.exit(); | |||
} | |||
} | |||
} | |||
} |
@@ -0,0 +1,59 @@ | |||
/* | |||
* Copyright 1999-2020 Alibaba Group Holding Ltd. | |||
* | |||
* Licensed 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 com.alibaba.csp.sentinel.adapter.okhttp.config; | |||
import com.alibaba.csp.sentinel.adapter.okhttp.extractor.DefaultOkHttpResourceExtractor; | |||
import com.alibaba.csp.sentinel.adapter.okhttp.extractor.OkHttpResourceExtractor; | |||
import com.alibaba.csp.sentinel.adapter.okhttp.fallback.DefaultOkHttpFallback; | |||
import com.alibaba.csp.sentinel.adapter.okhttp.fallback.OkHttpFallback; | |||
import com.alibaba.csp.sentinel.util.AssertUtil; | |||
/** | |||
* @author zhaoyuguang | |||
*/ | |||
public final class SentinelOkHttpConfig { | |||
private static volatile String prefix = "okhttp:"; | |||
private static volatile OkHttpResourceExtractor extractor = new DefaultOkHttpResourceExtractor(); | |||
private static volatile OkHttpFallback fallback = new DefaultOkHttpFallback(); | |||
public static String getPrefix() { | |||
return prefix; | |||
} | |||
public static void setPrefix(String prefix) { | |||
AssertUtil.notNull(prefix, "prefix cannot be null"); | |||
SentinelOkHttpConfig.prefix = prefix; | |||
} | |||
public static OkHttpResourceExtractor getExtractor() { | |||
return extractor; | |||
} | |||
public static void setExtractor(OkHttpResourceExtractor extractor) { | |||
AssertUtil.notNull(extractor, "extractor cannot be null"); | |||
SentinelOkHttpConfig.extractor = extractor; | |||
} | |||
public static OkHttpFallback getFallback() { | |||
return fallback; | |||
} | |||
public static void setFallback(OkHttpFallback fallback) { | |||
AssertUtil.notNull(fallback, "fallback cannot be null"); | |||
SentinelOkHttpConfig.fallback = fallback; | |||
} | |||
} |
@@ -0,0 +1,30 @@ | |||
/* | |||
* Copyright 1999-2020 Alibaba Group Holding Ltd. | |||
* | |||
* Licensed 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 com.alibaba.csp.sentinel.adapter.okhttp.extractor; | |||
import okhttp3.Connection; | |||
import okhttp3.Request; | |||
/** | |||
* @author zhaoyuguang | |||
*/ | |||
public class DefaultOkHttpResourceExtractor implements OkHttpResourceExtractor { | |||
@Override | |||
public String extract(String url, Request request, Connection connection) { | |||
return request.method() + ":" + request.url().toString(); | |||
} | |||
} |
@@ -0,0 +1,27 @@ | |||
/* | |||
* Copyright 1999-2020 Alibaba Group Holding Ltd. | |||
* | |||
* Licensed 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 com.alibaba.csp.sentinel.adapter.okhttp.extractor; | |||
import okhttp3.Connection; | |||
import okhttp3.Request; | |||
/** | |||
* @author zhaoyuguang | |||
*/ | |||
public interface OkHttpResourceExtractor { | |||
String extract(String url, Request request, Connection connection); | |||
} |
@@ -0,0 +1,34 @@ | |||
/* | |||
* Copyright 1999-2020 Alibaba Group Holding Ltd. | |||
* | |||
* Licensed 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 com.alibaba.csp.sentinel.adapter.okhttp.fallback; | |||
import com.alibaba.csp.sentinel.slots.block.BlockException; | |||
import com.alibaba.csp.sentinel.slots.block.SentinelRpcException; | |||
import okhttp3.Connection; | |||
import okhttp3.Request; | |||
import okhttp3.Response; | |||
/** | |||
* @author zhaoyuguang | |||
*/ | |||
public class DefaultOkHttpFallback implements OkHttpFallback { | |||
@Override | |||
public Response handle(Request request, Connection connection, BlockException e) { | |||
// Just wrap and throw the exception. | |||
throw new SentinelRpcException(e); | |||
} | |||
} |
@@ -0,0 +1,29 @@ | |||
/* | |||
* Copyright 1999-2020 Alibaba Group Holding Ltd. | |||
* | |||
* Licensed 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 com.alibaba.csp.sentinel.adapter.okhttp.fallback; | |||
import com.alibaba.csp.sentinel.slots.block.BlockException; | |||
import okhttp3.Connection; | |||
import okhttp3.Request; | |||
import okhttp3.Response; | |||
/** | |||
* @author zhaoyuguang | |||
*/ | |||
public interface OkHttpFallback { | |||
Response handle(Request request, Connection connection, BlockException e); | |||
} |
@@ -0,0 +1,97 @@ | |||
/* | |||
* Copyright 1999-2020 Alibaba Group Holding Ltd. | |||
* | |||
* Licensed 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 com.alibaba.csp.sentinel.adapter.okhttp; | |||
import com.alibaba.csp.sentinel.Constants; | |||
import com.alibaba.csp.sentinel.adapter.okhttp.app.TestApplication; | |||
import com.alibaba.csp.sentinel.adapter.okhttp.config.SentinelOkHttpConfig; | |||
import com.alibaba.csp.sentinel.adapter.okhttp.extractor.OkHttpResourceExtractor; | |||
import com.alibaba.csp.sentinel.node.ClusterNode; | |||
import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot; | |||
import okhttp3.Connection; | |||
import okhttp3.OkHttpClient; | |||
import okhttp3.Request; | |||
import org.junit.Test; | |||
import org.junit.runner.RunWith; | |||
import org.springframework.beans.factory.annotation.Value; | |||
import org.springframework.boot.test.context.SpringBootTest; | |||
import org.springframework.test.context.junit4.SpringRunner; | |||
import static org.junit.Assert.assertNotNull; | |||
/** | |||
* @author zhaoyuguang | |||
*/ | |||
@RunWith(SpringRunner.class) | |||
@SpringBootTest(classes = TestApplication.class, | |||
webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, | |||
properties = { | |||
"server.port=8086" | |||
}) | |||
public class SentinelOkHttpInterceptorTest { | |||
@Value("${server.port}") | |||
private Integer port; | |||
@Test | |||
public void testSentinelOkHttpInterceptor0() throws Exception { | |||
String url0 = "http://localhost:" + port + "/okhttp/back"; | |||
SentinelOkHttpConfig.setPrefix("okhttp:"); | |||
OkHttpClient client = new OkHttpClient.Builder() | |||
.addInterceptor(new SentinelOkHttpInterceptor()) | |||
.build(); | |||
Request request = new Request.Builder() | |||
.url(url0) | |||
.build(); | |||
System.out.println(client.newCall(request).execute().body().string()); | |||
ClusterNode cn = ClusterBuilderSlot.getClusterNode(SentinelOkHttpConfig.getPrefix() + "GET:" + url0); | |||
assertNotNull(cn); | |||
Constants.ROOT.removeChildList(); | |||
ClusterBuilderSlot.getClusterNodeMap().clear(); | |||
} | |||
@Test | |||
public void testSentinelOkHttpInterceptor1() throws Exception { | |||
String url0 = "http://localhost:" + port + "/okhttp/back/1"; | |||
SentinelOkHttpConfig.setExtractor(new OkHttpResourceExtractor() { | |||
@Override | |||
public String extract(String url, Request request, Connection connection) { | |||
String regex = "/okhttp/back/"; | |||
if (url.contains(regex)) { | |||
url = url.substring(0, url.indexOf(regex) + regex.length()) + "{id}"; | |||
} | |||
return request.method() + ":" + url; | |||
} | |||
}); | |||
OkHttpClient client = new OkHttpClient.Builder() | |||
.addInterceptor(new SentinelOkHttpInterceptor()) | |||
.build(); | |||
Request request = new Request.Builder() | |||
.url(url0) | |||
.build(); | |||
System.out.println(client.newCall(request).execute().body().string()); | |||
String url1 = SentinelOkHttpConfig.getPrefix() + "GET:http://localhost:" + port + "/okhttp/back/{id}"; | |||
ClusterNode cn = ClusterBuilderSlot.getClusterNode(url1); | |||
assertNotNull(cn); | |||
Constants.ROOT.removeChildList(); | |||
ClusterBuilderSlot.getClusterNodeMap().clear(); | |||
} | |||
} |
@@ -0,0 +1,30 @@ | |||
/* | |||
* Copyright 1999-2020 Alibaba Group Holding Ltd. | |||
* | |||
* Licensed 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 com.alibaba.csp.sentinel.adapter.okhttp.app; | |||
import org.springframework.boot.SpringApplication; | |||
import org.springframework.boot.autoconfigure.SpringBootApplication; | |||
/** | |||
* @author zhaoyuguang | |||
*/ | |||
@SpringBootApplication | |||
public class TestApplication { | |||
public static void main(String[] args) { | |||
SpringApplication.run(TestApplication.class); | |||
} | |||
} |
@@ -0,0 +1,37 @@ | |||
/* | |||
* Copyright 1999-2020 Alibaba Group Holding Ltd. | |||
* | |||
* Licensed 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 com.alibaba.csp.sentinel.adapter.okhttp.app.controller; | |||
import org.springframework.web.bind.annotation.PathVariable; | |||
import org.springframework.web.bind.annotation.RequestMapping; | |||
import org.springframework.web.bind.annotation.RestController; | |||
/** | |||
* @author zhaoyuguang | |||
*/ | |||
@RestController | |||
public class TestController { | |||
@RequestMapping("/okhttp/back") | |||
public String back() { | |||
return "Welcome Back!"; | |||
} | |||
@RequestMapping("/okhttp/back/{id}") | |||
public String back(@PathVariable String id) { | |||
return "Welcome Back! " + id; | |||
} | |||
} |
@@ -0,0 +1,39 @@ | |||
/* | |||
* Copyright 1999-2020 Alibaba Group Holding Ltd. | |||
* | |||
* Licensed 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 com.alibaba.csp.sentinel.adapter.okhttp.config; | |||
import org.junit.Test; | |||
/** | |||
* @author zhaoyuguang | |||
*/ | |||
public class SentinelOkHttpConfigTest { | |||
@Test(expected = IllegalArgumentException.class) | |||
public void testConfigSetPrefix() { | |||
SentinelOkHttpConfig.setPrefix(null); | |||
} | |||
@Test(expected = IllegalArgumentException.class) | |||
public void testConfigSetCleaner() { | |||
SentinelOkHttpConfig.setExtractor(null); | |||
} | |||
@Test(expected = IllegalArgumentException.class) | |||
public void testConfigSetFallback() { | |||
SentinelOkHttpConfig.setFallback(null); | |||
} | |||
} |
@@ -0,0 +1,61 @@ | |||
/* | |||
* Copyright 1999-2020 Alibaba Group Holding Ltd. | |||
* | |||
* Licensed 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 com.alibaba.csp.sentinel.adapter.okhttp.extractor; | |||
import com.alibaba.csp.sentinel.adapter.okhttp.config.SentinelOkHttpConfig; | |||
import okhttp3.Connection; | |||
import okhttp3.Request; | |||
import org.junit.Test; | |||
import static org.junit.Assert.assertEquals; | |||
/** | |||
* @author zhaoyuguang | |||
*/ | |||
public class OkHttpResourceExtractorTest { | |||
@Test | |||
public void testDefaultOkHttpResourceExtractor() { | |||
OkHttpResourceExtractor extractor = new DefaultOkHttpResourceExtractor(); | |||
String url = "http://localhost:8083/okhttp/back"; | |||
Request request = new Request.Builder() | |||
.url(url) | |||
.build(); | |||
extractor.extract(url, request, null); | |||
System.out.println(extractor.extract(url, request, null)); | |||
assertEquals("GET:"+url, extractor.extract(url, request, null)); | |||
} | |||
@Test | |||
public void testCustomizeOkHttpUrlCleaner() { | |||
OkHttpResourceExtractor extractor = new OkHttpResourceExtractor() { | |||
@Override | |||
public String extract(String url, Request request, Connection connection) { | |||
String regex = "/okhttp/back/"; | |||
if (url.contains(regex)) { | |||
url = url.substring(0, url.indexOf(regex) + regex.length()) + "{id}"; | |||
} | |||
return request.method() + ":" + url; | |||
} | |||
}; | |||
String url = "http://localhost:8083/okhttp/back/abc"; | |||
Request request = new Request.Builder() | |||
.url(url) | |||
.build(); | |||
extractor.extract(url, request, null); | |||
assertEquals("GET:http://localhost:8083/okhttp/back/{id}", extractor.extract(url, request, null)); | |||
} | |||
} |
@@ -0,0 +1,34 @@ | |||
/* | |||
* Copyright 1999-2020 Alibaba Group Holding Ltd. | |||
* | |||
* Licensed 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 com.alibaba.csp.sentinel.adapter.okhttp.fallback; | |||
import com.alibaba.csp.sentinel.slots.block.BlockException; | |||
import com.alibaba.csp.sentinel.slots.block.SentinelRpcException; | |||
import com.alibaba.csp.sentinel.slots.block.flow.FlowException; | |||
import org.junit.Test; | |||
/** | |||
* @author zhaoyuguang | |||
*/ | |||
public class OkHttpFallbackTest { | |||
@Test(expected = SentinelRpcException.class) | |||
public void testDefaultOkHttpFallback() { | |||
BlockException e = new FlowException("xxx"); | |||
OkHttpFallback fallback = new DefaultOkHttpFallback(); | |||
fallback.handle(null, null, e); | |||
} | |||
} |
@@ -39,6 +39,7 @@ | |||
<module>sentinel-demo-spring-webmvc</module> | |||
<module>sentinel-demo-zuul2-gateway</module> | |||
<module>sentinel-demo-log-logback</module> | |||
<module>sentinel-demo-okhttp</module> | |||
<module>sentinel-demo-jax-rs</module> | |||
</modules> | |||
@@ -0,0 +1,45 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<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"> | |||
<parent> | |||
<artifactId>sentinel-demo</artifactId> | |||
<groupId>com.alibaba.csp</groupId> | |||
<version>1.8.0-SNAPSHOT</version> | |||
</parent> | |||
<modelVersion>4.0.0</modelVersion> | |||
<artifactId>sentinel-demo-okhttp</artifactId> | |||
<properties> | |||
<spring.boot.version>2.1.3.RELEASE</spring.boot.version> | |||
<okhttp.version>3.6.0</okhttp.version> | |||
</properties> | |||
<dependencies> | |||
<dependency> | |||
<groupId>com.alibaba.csp</groupId> | |||
<artifactId>sentinel-transport-simple-http</artifactId> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.alibaba.csp</groupId> | |||
<artifactId>sentinel-okhttp-adapter</artifactId> | |||
<version>${project.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-starter-web</artifactId> | |||
<version>${spring.boot.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>org.springframework.boot</groupId> | |||
<artifactId>spring-boot-starter-test</artifactId> | |||
<version>${spring.boot.version}</version> | |||
</dependency> | |||
<dependency> | |||
<groupId>com.squareup.okhttp3</groupId> | |||
<artifactId>okhttp</artifactId> | |||
<version>${okhttp.version}</version> | |||
</dependency> | |||
</dependencies> | |||
</project> |
@@ -0,0 +1,49 @@ | |||
/* | |||
* Copyright 1999-2020 Alibaba Group Holding Ltd. | |||
* | |||
* Licensed 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 com.alibaba.csp.sentinel.demo.okhttp; | |||
import com.alibaba.csp.sentinel.adapter.okhttp.config.SentinelOkHttpConfig; | |||
import com.alibaba.csp.sentinel.adapter.okhttp.extractor.OkHttpResourceExtractor; | |||
import okhttp3.Connection; | |||
import okhttp3.Request; | |||
import org.springframework.boot.CommandLineRunner; | |||
import org.springframework.boot.SpringApplication; | |||
import org.springframework.boot.autoconfigure.SpringBootApplication; | |||
/** | |||
* @author zhaoyuguang | |||
*/ | |||
@SpringBootApplication | |||
public class OkHttpDemoApplication implements CommandLineRunner { | |||
public static void main(String[] args) { | |||
SpringApplication.run(OkHttpDemoApplication.class); | |||
} | |||
@Override | |||
public void run(String... args) { | |||
SentinelOkHttpConfig.setExtractor(new OkHttpResourceExtractor() { | |||
@Override | |||
public String extract(String url, Request request, Connection connection) { | |||
String regex = "/okhttp/back/"; | |||
if (url.contains(regex)) { | |||
url = url.substring(0, url.indexOf(regex) + regex.length()) + "{id}"; | |||
} | |||
return request.method() + ":" + url; | |||
} | |||
}); | |||
} | |||
} |
@@ -0,0 +1,68 @@ | |||
/* | |||
* Copyright 1999-2020 Alibaba Group Holding Ltd. | |||
* | |||
* Licensed 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 com.alibaba.csp.sentinel.demo.okhttp.controller; | |||
import com.alibaba.csp.sentinel.adapter.okhttp.SentinelOkHttpInterceptor; | |||
import okhttp3.OkHttpClient; | |||
import okhttp3.Request; | |||
import okhttp3.Response; | |||
import org.springframework.beans.factory.annotation.Value; | |||
import org.springframework.web.bind.annotation.PathVariable; | |||
import org.springframework.web.bind.annotation.RequestMapping; | |||
import org.springframework.web.bind.annotation.RestController; | |||
import java.io.IOException; | |||
/** | |||
* @author zhaoyuguang | |||
*/ | |||
@RestController | |||
public class OkHttpTestController { | |||
@Value("${server.port}") | |||
private Integer port; | |||
@RequestMapping("/okhttp/back") | |||
public String back() { | |||
return "Welcome Back!"; | |||
} | |||
@RequestMapping("/okhttp/back/{id}") | |||
public String back(@PathVariable String id) { | |||
return "Welcome Back! " + id; | |||
} | |||
@RequestMapping("/okhttp/testcase/{id}") | |||
public String testcase(@PathVariable String id) throws Exception { | |||
return getRemoteString(id); | |||
} | |||
@RequestMapping("/okhttp/testcase") | |||
public String testcase() throws Exception { | |||
return getRemoteString(null); | |||
} | |||
private String getRemoteString(String id) throws IOException { | |||
OkHttpClient client = new OkHttpClient.Builder() | |||
.addInterceptor(new SentinelOkHttpInterceptor()) | |||
.build(); | |||
Request request = new Request.Builder() | |||
.url("http://localhost:" + port + "/okhttp/back" + (id == null ? "" : "/" + id)) | |||
.build(); | |||
Response response = client.newCall(request).execute(); | |||
return response.body().string(); | |||
} | |||
} |
@@ -0,0 +1,2 @@ | |||
spring.application.name=sentinel-demo-okhttp | |||
server.port=8085 |