@Override
	public Response execute(Request request, Options options) throws IOException {
		EnhancedPluginContext enhancedPluginContext = new EnhancedPluginContext();

		HttpHeaders requestHeaders = new HttpHeaders();
		request.headers().forEach((s, strings) -> requestHeaders.addAll(s, new ArrayList<>(strings)));
		URI url = URI.create(request.url());

		EnhancedRequestContext enhancedRequestContext = EnhancedRequestContext.builder()
				.httpHeaders(requestHeaders)
				.httpMethod(HttpMethod.valueOf(request.httpMethod().name()))
				.url(url)
				.build();
		enhancedPluginContext.setRequest(enhancedRequestContext);
		enhancedPluginContext.setOriginRequest(request);

		enhancedPluginContext.setLocalServiceInstance(pluginRunner.getLocalServiceInstance());
		String svcName = request.requestTemplate().feignTarget().name();
		DefaultServiceInstance serviceInstance = new DefaultServiceInstance(
				String.format("%s-%s-%d", svcName, url.getHost(), url.getPort()),
				svcName, url.getHost(), url.getPort(), url.getScheme().equals("https"));
		// -1 means access directly by url
		if (serviceInstance.getPort() == -1) {
			enhancedPluginContext.setTargetServiceInstance(null, url);
		}
		else {
			enhancedPluginContext.setTargetServiceInstance(serviceInstance, url);
		}

		// Run pre enhanced plugins.
		pluginRunner.run(EnhancedPluginType.Client.PRE, enhancedPluginContext);

		long startMillis = System.currentTimeMillis();
		try {
			Response response = delegate.execute(request, options);
			enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis);

			HttpHeaders responseHeaders = new HttpHeaders();
			response.headers().forEach((s, strings) -> responseHeaders.addAll(s, new ArrayList<>(strings)));

			EnhancedResponseContext enhancedResponseContext = EnhancedResponseContext.builder()
					.httpStatus(response.status())
					.httpHeaders(responseHeaders)
					.build();
			enhancedPluginContext.setResponse(enhancedResponseContext);

			// Run post enhanced plugins.
			pluginRunner.run(EnhancedPluginType.Client.POST, enhancedPluginContext);
			return response;
		}
		catch (IOException origin) {
			enhancedPluginContext.setDelay(System.currentTimeMillis() - startMillis);
			enhancedPluginContext.setThrowable(origin);
			// Run exception enhanced feign plugins.
			pluginRunner.run(EnhancedPluginType.Client.EXCEPTION, enhancedPluginContext);
			throw origin;
		}
		finally {
			// Run finally enhanced plugins.
			pluginRunner.run(EnhancedPluginType.Client.FINALLY, enhancedPluginContext);
		}
	}
@Test
	public void testExecute() throws IOException {
		// mock Client.class
		Client delegate = mock(Client.class);
		doAnswer(invocation -> {
			Request request = invocation.getArgument(0);
			if (request.httpMethod().equals(Request.HttpMethod.GET)) {
				return Response.builder().request(request).status(200).build();
			}
			else if (request.httpMethod().equals(Request.HttpMethod.POST)) {
				return Response.builder().request(request).status(502).build();
			}
			throw new IOException("Mock exception.");
		}).when(delegate).execute(any(Request.class), nullable(Request.Options.class));

		// mock target
		Target<Object> target = Target.EmptyTarget.create(Object.class);

		// mock RequestTemplate.class
		RequestTemplate requestTemplate = new RequestTemplate();
		requestTemplate.feignTarget(target);

		EnhancedFeignClient polarisFeignClient = new EnhancedFeignClient(delegate,
				new DefaultEnhancedPluginRunner(getMockEnhancedFeignPlugins(), null, polarisSDKContextManager.getSDKContext()));

		// 200
		Response response = polarisFeignClient.execute(Request.create(Request.HttpMethod.GET, "http://localhost:8080/test",
				Collections.emptyMap(), null, requestTemplate), null);
		assertThat(response.status()).isEqualTo(200);

		// 502
		response = polarisFeignClient.execute(Request.create(Request.HttpMethod.POST, "http://localhost:8080/test",
				Collections.emptyMap(), null, requestTemplate), null);
		assertThat(response.status()).isEqualTo(502);

		// Exception
		try {
			polarisFeignClient.execute(Request.create(Request.HttpMethod.DELETE, "http://localhost:8080/test",
					Collections.emptyMap(), null, requestTemplate), null);
			fail("IOException should be thrown.");
		}
		catch (Throwable t) {
			assertThat(t).isInstanceOf(IOException.class);
			assertThat(t.getMessage()).isEqualTo("Mock exception.");
		}
	}