mirror of
				https://github.com/nsnail/Ocelot.git
				synced 2025-10-31 15:45:28 +08:00 
			
		
		
		
	fixed problems where routes were not mathing
This commit is contained in:
		| @@ -122,6 +122,8 @@ Ocelot's primary functionality is to take incomeing http requests and forward th | ||||
| to a downstream service. At the moment in the form of another http request (in the future | ||||
| this could be any transport mechanism.).  | ||||
|  | ||||
| Ocelot always adds a trailing slash to an UpstreamTemplate. | ||||
|  | ||||
| Ocelot's describes the routing of one request to another as a ReRoute. In order to get  | ||||
| anything working in Ocelot you need to set up a ReRoute in the configuration. | ||||
|  | ||||
|   | ||||
| @@ -1,9 +1,11 @@ | ||||
| { | ||||
| 	"ReRoutes": [ | ||||
| 		{ | ||||
| 			# The url we are forwarding the request to | ||||
| 			"UpstreamTemplate": "/identityserverexample", | ||||
| 			# The path we are listening on for this re route | ||||
| 			# The url we are forwarding the request to, ocelot will not add a trailing slash | ||||
| 			"DownstreamTemplate": "http://somehost.com/identityserverexample", | ||||
| 			# The path we are listening on for this re route, Ocelot will add a trailing slash to | ||||
| 			# this property. Then when a request is made Ocelot makes sure a trailing slash is added | ||||
| 			# to that so everything matches | ||||
| 			"UpstreamTemplate": "/identityserverexample", | ||||
| 			# The method we are listening for on this re route | ||||
| 			"UpstreamHttpMethod": "Get", | ||||
|   | ||||
| @@ -7,6 +7,7 @@ using Ocelot.Configuration.File; | ||||
| using Ocelot.Configuration.Parser; | ||||
| using Ocelot.Configuration.Validator; | ||||
| using Ocelot.Responses; | ||||
| using Ocelot.Utilities; | ||||
|  | ||||
| namespace Ocelot.Configuration.Creator | ||||
| { | ||||
| @@ -90,7 +91,6 @@ namespace Ocelot.Configuration.Creator | ||||
|                 ? globalConfiguration.RequestIdKey | ||||
|                 : reRoute.RequestIdKey; | ||||
|  | ||||
|  | ||||
|             if (isAuthenticated) | ||||
|             { | ||||
|                 var authOptionsForRoute = new AuthenticationOptions(reRoute.AuthenticationOptions.Provider, | ||||
| @@ -120,6 +120,8 @@ namespace Ocelot.Configuration.Creator | ||||
|         { | ||||
|             var upstreamTemplate = reRoute.UpstreamTemplate; | ||||
|  | ||||
|             upstreamTemplate = upstreamTemplate.SetLastCharacterAs('/'); | ||||
|  | ||||
|             var placeholders = new List<string>(); | ||||
|  | ||||
|             for (var i = 0; i < upstreamTemplate.Length; i++) | ||||
| @@ -138,9 +140,11 @@ namespace Ocelot.Configuration.Creator | ||||
|                 upstreamTemplate = upstreamTemplate.Replace(placeholder, RegExMatchEverything); | ||||
|             } | ||||
|  | ||||
|             return reRoute.ReRouteIsCaseSensitive  | ||||
|             var route = reRoute.ReRouteIsCaseSensitive  | ||||
|                 ? $"{upstreamTemplate}{RegExMatchEndString}"  | ||||
|                 : $"{RegExIgnoreCase}{upstreamTemplate}{RegExMatchEndString}"; | ||||
|  | ||||
|             return route; | ||||
|         } | ||||
|  | ||||
|         private List<ClaimToThing> GetAddThingsToRequest(Dictionary<string,string> thingBeingAdded) | ||||
|   | ||||
| @@ -5,6 +5,7 @@ using Ocelot.DownstreamRouteFinder.Finder; | ||||
| using Ocelot.Infrastructure.RequestData; | ||||
| using Ocelot.Logging; | ||||
| using Ocelot.Middleware; | ||||
| using Ocelot.Utilities; | ||||
|  | ||||
| namespace Ocelot.DownstreamRouteFinder.Middleware | ||||
| { | ||||
| @@ -29,7 +30,7 @@ namespace Ocelot.DownstreamRouteFinder.Middleware | ||||
|         { | ||||
|             _logger.LogDebug("started calling downstream route finder middleware"); | ||||
|  | ||||
|             var upstreamUrlPath = context.Request.Path.ToString(); | ||||
|             var upstreamUrlPath = context.Request.Path.ToString().SetLastCharacterAs('/'); | ||||
|  | ||||
|             _logger.LogDebug("upstream url path is {upstreamUrlPath}", upstreamUrlPath); | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| using System; | ||||
| using System.IO; | ||||
| using System.Threading.Tasks; | ||||
| using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.Extensions.Logging; | ||||
| @@ -46,14 +47,16 @@ namespace Ocelot.Errors.Middleware | ||||
|             _logger.LogDebug("ocelot pipeline finished"); | ||||
|         } | ||||
|  | ||||
|         private static async Task SetInternalServerErrorOnResponse(HttpContext context) | ||||
|         private async Task SetInternalServerErrorOnResponse(HttpContext context) | ||||
|         { | ||||
|             context.Response.StatusCode = 500; | ||||
|             context.Response.ContentType = "application/json"; | ||||
|             await context.Response.WriteAsync("Internal Server Error"); | ||||
|             context.Response.OnStarting(x => | ||||
|             { | ||||
|                 context.Response.StatusCode = 500; | ||||
|                 return Task.CompletedTask; | ||||
|             }, context); | ||||
|         } | ||||
|  | ||||
|         private static string CreateMessage(HttpContext context, Exception e) | ||||
|         private string CreateMessage(HttpContext context, Exception e) | ||||
|         { | ||||
|             var message = | ||||
|                 $"Exception caught in global error handler, exception message: {e.Message}, exception stack: {e.StackTrace}"; | ||||
|   | ||||
							
								
								
									
										17
									
								
								src/Ocelot/Utilities/StringExtensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/Ocelot/Utilities/StringExtensions.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| namespace Ocelot.Utilities | ||||
| { | ||||
|     public static class StringExtensions | ||||
|     { | ||||
|         public static string SetLastCharacterAs(this string valueToSetLastChar,  | ||||
|             char expectedLastChar) | ||||
|         { | ||||
|             var last = valueToSetLastChar[valueToSetLastChar.Length - 1]; | ||||
|  | ||||
|             if (last != expectedLastChar) | ||||
|             { | ||||
|                 valueToSetLastChar = $"{valueToSetLastChar}{expectedLastChar}"; | ||||
|             } | ||||
|             return valueToSetLastChar; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -56,6 +56,80 @@ namespace Ocelot.AcceptanceTests | ||||
|                 .BDDfy(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void should_not_care_about_no_trailing() | ||||
|         { | ||||
|             var configuration = new FileConfiguration | ||||
|             { | ||||
|                 ReRoutes = new List<FileReRoute> | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:51879/products", | ||||
|                             UpstreamTemplate = "/products/", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                         } | ||||
|                     } | ||||
|             }; | ||||
|  | ||||
|             this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879/products", 200, "Hello from Laura")) | ||||
|                 .And(x => _steps.GivenThereIsAConfiguration(configuration)) | ||||
|                 .And(x => _steps.GivenOcelotIsRunning()) | ||||
|                 .When(x => _steps.WhenIGetUrlOnTheApiGateway("/products")) | ||||
|                 .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) | ||||
|                 .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura")) | ||||
|                 .BDDfy(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void should_not_care_about_trailing() | ||||
|         { | ||||
|             var configuration = new FileConfiguration | ||||
|             { | ||||
|                 ReRoutes = new List<FileReRoute> | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:51879/products", | ||||
|                             UpstreamTemplate = "/products", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                         } | ||||
|                     } | ||||
|             }; | ||||
|  | ||||
|             this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879/products", 200, "Hello from Laura")) | ||||
|                 .And(x => _steps.GivenThereIsAConfiguration(configuration)) | ||||
|                 .And(x => _steps.GivenOcelotIsRunning()) | ||||
|                 .When(x => _steps.WhenIGetUrlOnTheApiGateway("/products/")) | ||||
|                 .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK)) | ||||
|                 .And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura")) | ||||
|                 .BDDfy(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void should_return_not_found() | ||||
|         { | ||||
|             var configuration = new FileConfiguration | ||||
|             { | ||||
|                 ReRoutes = new List<FileReRoute> | ||||
|                     { | ||||
|                         new FileReRoute | ||||
|                         { | ||||
|                             DownstreamTemplate = "http://localhost:51879/products", | ||||
|                             UpstreamTemplate = "/products/{productId}", | ||||
|                             UpstreamHttpMethod = "Get", | ||||
|                         } | ||||
|                     } | ||||
|             }; | ||||
|  | ||||
|             this.Given(x => x.GivenThereIsAServiceRunningOn("http://localhost:51879/products", 200, "Hello from Laura")) | ||||
|                 .And(x => _steps.GivenThereIsAConfiguration(configuration)) | ||||
|                 .And(x => _steps.GivenOcelotIsRunning()) | ||||
|                 .When(x => _steps.WhenIGetUrlOnTheApiGateway("/products/")) | ||||
|                 .Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.NotFound)) | ||||
|                 .BDDfy(); | ||||
|         } | ||||
|  | ||||
|         [Fact] | ||||
|         public void should_return_response_200_with_complex_url() | ||||
|         { | ||||
|   | ||||
| @@ -137,6 +137,12 @@ | ||||
|             "UpstreamTemplate": "/customers/{customerId}", | ||||
|             "UpstreamHttpMethod": "Delete", | ||||
|             "FileCacheOptions": { "TtlSeconds": 15 } | ||||
|         }, | ||||
|         { | ||||
|             "DownstreamTemplate": "http://jsonplaceholder.typicode.com/posts", | ||||
|             "UpstreamTemplate": "/posts/", | ||||
|             "UpstreamHttpMethod": "Get", | ||||
|             "FileCacheOptions": { "TtlSeconds": 15 } | ||||
|         } | ||||
|     ], | ||||
|     "GlobalConfiguration": { | ||||
|   | ||||
| @@ -59,7 +59,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                         .WithDownstreamTemplate("/products/{productId}") | ||||
|                         .WithUpstreamTemplate("/api/products/{productId}") | ||||
|                         .WithUpstreamHttpMethod("Get") | ||||
|                         .WithUpstreamTemplatePattern("(?i)/api/products/.*$") | ||||
|                         .WithUpstreamTemplatePattern("(?i)/api/products/.*/$") | ||||
|                         .Build() | ||||
|                 })) | ||||
|                 .BDDfy(); | ||||
| @@ -88,7 +88,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                         .WithDownstreamTemplate("/products/{productId}") | ||||
|                         .WithUpstreamTemplate("/api/products/{productId}") | ||||
|                         .WithUpstreamHttpMethod("Get") | ||||
|                         .WithUpstreamTemplatePattern("(?i)/api/products/.*$") | ||||
|                         .WithUpstreamTemplatePattern("(?i)/api/products/.*/$") | ||||
|                         .Build() | ||||
|                 })) | ||||
|                 .BDDfy(); | ||||
| @@ -118,7 +118,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                         .WithDownstreamTemplate("/products/{productId}") | ||||
|                         .WithUpstreamTemplate("/api/products/{productId}") | ||||
|                         .WithUpstreamHttpMethod("Get") | ||||
|                         .WithUpstreamTemplatePattern("/api/products/.*$") | ||||
|                         .WithUpstreamTemplatePattern("/api/products/.*/$") | ||||
|                         .Build() | ||||
|               })) | ||||
|               .BDDfy(); | ||||
| @@ -152,7 +152,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                         .WithDownstreamTemplate("/products/{productId}") | ||||
|                         .WithUpstreamTemplate("/api/products/{productId}") | ||||
|                         .WithUpstreamHttpMethod("Get") | ||||
|                         .WithUpstreamTemplatePattern("/api/products/.*$") | ||||
|                         .WithUpstreamTemplatePattern("/api/products/.*/$") | ||||
|                         .WithRequestIdKey("blahhhh") | ||||
|                         .Build() | ||||
|                 })) | ||||
| @@ -183,7 +183,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                         .WithDownstreamTemplate("/products/{productId}") | ||||
|                         .WithUpstreamTemplate("/api/products/{productId}") | ||||
|                         .WithUpstreamHttpMethod("Get") | ||||
|                         .WithUpstreamTemplatePattern("/api/products/.*$") | ||||
|                         .WithUpstreamTemplatePattern("/api/products/.*/$") | ||||
|                         .Build() | ||||
|                 })) | ||||
|                 .BDDfy(); | ||||
| @@ -198,7 +198,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                     .WithDownstreamTemplate("/products/{productId}") | ||||
|                     .WithUpstreamTemplate("/api/products/{productId}") | ||||
|                     .WithUpstreamHttpMethod("Get") | ||||
|                     .WithUpstreamTemplatePattern("/api/products/.*$") | ||||
|                     .WithUpstreamTemplatePattern("/api/products/.*/$") | ||||
|                     .WithAuthenticationProvider("IdentityServer") | ||||
|                     .WithAuthenticationProviderUrl("http://localhost:51888") | ||||
|                     .WithRequireHttps(false) | ||||
| @@ -261,7 +261,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                     .WithDownstreamTemplate("/products/{productId}") | ||||
|                     .WithUpstreamTemplate("/api/products/{productId}") | ||||
|                     .WithUpstreamHttpMethod("Get") | ||||
|                     .WithUpstreamTemplatePattern("/api/products/.*$") | ||||
|                     .WithUpstreamTemplatePattern("/api/products/.*/$") | ||||
|                     .WithAuthenticationProvider("IdentityServer") | ||||
|                     .WithAuthenticationProviderUrl("http://localhost:51888") | ||||
|                     .WithRequireHttps(false) | ||||
| @@ -323,7 +323,7 @@ namespace Ocelot.UnitTests.Configuration | ||||
|                         .WithDownstreamTemplate("/products/{productId}") | ||||
|                         .WithUpstreamTemplate("/api/products/{productId}/variants/{variantId}") | ||||
|                         .WithUpstreamHttpMethod("Get") | ||||
|                         .WithUpstreamTemplatePattern("/api/products/.*/variants/.*$") | ||||
|                         .WithUpstreamTemplatePattern("/api/products/.*/variants/.*/$") | ||||
|                         .Build() | ||||
|                 })) | ||||
|                 .BDDfy(); | ||||
|   | ||||
| @@ -148,7 +148,6 @@ namespace Ocelot.UnitTests.DownstreamRouteFinder.UrlMatcher | ||||
|               .BDDfy(); | ||||
|         } | ||||
|  | ||||
|  | ||||
|         private void GivenIHaveAUpstreamPath(string downstreamPath) | ||||
|         { | ||||
|             _downstreamUrlPath = downstreamPath; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 TomPallister
					TomPallister