Ocelot API gateway setting only TimeOut value throwing error - asp.net-core

According to Ocelot document Quality Of Service we can metion only TimeOutValue in Routes, like
"QoSOptions": {
"TimeoutValue":5000
}
but this is throwing exception like
Ocelot.Requester.Middleware.HttpRequesterMiddleware: Debug: requestId: 800002b3-0002-fd00-b63f-84710c7967bb, previousRequestId: no previous request id, message: IHttpRequester returned an error, setting pipeline error
Ocelot.Responder.Middleware.ResponderMiddleware: Warning: requestId: 800002b3-0002-fd00-b63f-84710c7967bb, previousRequestId: no previous request id, message: Error Code: UnableToCompleteRequestError Message: Error making http request, exception: System.ArgumentException: The enumerable of policies to form the wrap must contain at least two policies. (Parameter 'policies')
at Polly.Policy.WrapAsync(IAsyncPolicy[] policies)
at Ocelot.Provider.Polly.PollyCircuitBreakingDelegatingHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
at Ocelot.Requester.HttpClientHttpRequester.GetResponse(HttpContext httpContext) errors found in ResponderMiddleware. Setting error response for request path:/api/v1/cust/clients, request method: GET
Ocelot.Errors.Middleware.ExceptionHandlerMiddleware: Debug: requestId: 800002b3-0002-fd00-b63f-84710c7967bb, previousRequestId: no previous request id, message: ocelot pipeline finished
Microsoft.AspNetCore.Hosting.Diagnostics: Information: Request finished in 200.2779ms 500
My Route configuration is
{
"Routes": [
{
"DownstreamPathTemplate": "/api/{version}/cust/{everything}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{
"Host": "localhost",
"Port": 5001
}
],
"UpstreamPathTemplate": "/api/{version}/cust/{everything}",
"UpstreamHttpMethod": [],
"QoSOptions": {
"TimeoutValue": 900000
}
}
],
"GlobalConfiguration": {
"RequestIdKey": "OcRequestId",
"AdministrationPath": "/administration"
}
}
My .Net Core version is 3.1 and Ocelet version is 16.0.1

Maybe some issue by having only one policy (the timeout policy).
I have to add the Circuit Break settings to make this work:
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking":99999,
"DurationOfBreak":0,
"TimeoutValue":5000
}

Related

mail.send is not accepting HTML/ CSS code

I have copied the (HTML) source code from a received email just to have the template/format of that email, and this is the error message that I am receiveing when running the API:
Internal : Unexpected error Error during Web API HTTP Request
HTTP Status Code: 400
HTTP Response Content: {
"error": {
"code": "BadRequest",
"message": "Unable to read JSON request payload. Please ensure Content-Type header is set and payload is of valid JSON format.",
"innerError": {
"date": "2020-12-02T17:01:05",
"request-id": "3ab50fc1-0c13-4536-96db-bf6b9b7a736d",
"client-request-id": "3ab50fc1-0c13-4536-96db-bf6b9b7a736d"
}
}
}
I have tested basic commands using HTML such as making text bold and line breaks which work, but anything more complex and I will receive an error.
Update**
Thank you for your response guys, the call that I'm using looks like this:
{
"message": {
"subject": "[Subject]",
"body": {
"contentType": "HTML",
"content": "[Email Body Content]"
},
"toRecipients": [
{
"emailAddress": {
"address": "[Email Address]"
}
}
],
"internetMessageHeaders":[
{
"name":"x-custom-header-group-name",
"value":"Nevada"
},
{
"name":"x-custom-header-group-id",
"value":"NV001"
}
]
}
}
**Another update ** Upon changing the content type to text/html is recieved this error:
Internal : Unexpected error Error during Web API HTTP Request
HTTP Status Code: 415
HTTP Response Content: {"error":{"code":"RequestBodyRead","message":"A supported MIME type could not be found that matches the content type of the response. None of the supported type(s) 'Microsoft.OData.ODataMediaType, Microsoft.OData.ODataMediaTyp...' matches the content type 'text/plain; charset=utf-8'."}}
note i also have tried text/plain as the content type.
Thank you
Ok, I tried the above payload (just updated the email address) and tested with Microsoft Graph Explorer. It works for me :)
Here's the payload:
{"message":{"subject":"[Subject]","body":{"contentType":"HTML","content":"[Email Body Content]"},"toRecipients":[{"emailAddress":{"address":"test#domain.onmicrosoft.com"}}],"internetMessageHeaders":[{"name":"x-custom-header-group-name","value":"Nevada"},{"name":"x-custom-header-group-id","value":"NV001"}]}}
Here's the snapshot:

Why is jersey causing process error messages when sending an http get request

I'm trying to confirm that the get request is sent successfuly with a simple response of "It Works!" but I keep getting error message from Jersey api which is not specific
com.sun.jersey.spi.inject.Errors processErrorMessages
Caused by: com.sun.jersey.api.NotFoundException: null for uri: http://localhost:8080/sso/customconfigs
This is my code:
#Path("http://localhost:8080/sso/customconfigs")
#NoAuthRequired
class SSOCustomConfigsResource {
#GET
fun sendConfigs(): Response {
return Response.ok("It Works!").build()
}
}
This is what I get when sending the request
{
"identifier": 70004,
"statusCode": 404,
"message": "The path '/sso/customconfigs' is not available.",
"type": "NotFoundException"
}
I get the same error when trying to send requests to other endpoints.

WebSocket is not in the OPEN state

I'm trying SignalR on ASP.NET Core. It works fine running from VisaulStudio debugger.
However it does not work in deployed code, showing the error message "WebSocket is not in the OPEN state" and "Handshake was canceled". What is the possible cause of the problem?
Microsoft.AspNetCore.Mvc 2.2.0
Microsoft.AspNetCore.SignalR 1.1.0
#aspnet/signalr 1.1.2
Bootstrap4
jQuery v3.1.0
Kestrel
No HTTPS SSL
Tried with Windows 7 and Ubuntu 18.4
Network Console on Google Chrome
WebSocket is not in the OPEN state (kms-event-exit.js:12)
Uncaught Error: Seerver returned handshake error: Handshake was canceled. (signalr.min.js:16)
at HubConnection.processHandshakeResponse (signalr.min.js:16)
at HubConnection.processIncomingData (signalr.min.js:16)
at WebSocketTransport.HubConnection.connection.onreceive (signalr.min.js:16)
at WebSocket.webSocket.onmessag (signalr.min.js:16)
[2019-04-06T01:06:41.965Z] Error: Connection disconnected with error 'Error: Server returned handshake error: Handshake was canceled.'. signalr.min.js:16
Uncaught (in promise) Server returned handshake error: Handshake was canceled. (signalr.min.js:16)
Startup functions.
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
.AddRazorOptions(options => options.AllowRecompilingViewsOnFileChange = true);
services.AddSignalR(options => options.EnableDetailedErrors = true);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseDeveloperExceptionPage();
if (!env.IsDevelopment())
{
//app.UseExceptionHandler("/Home/Main");
app.UseHsts();
}
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseSignalR(routes =>
{
routes.MapHub<Hubs.KmsHub>("/KmsHub");
routes.MapHub<Hubs.AllResetHub>("/AllResetHub");
});
app.UseMvc(routes =>
{
routes.MapRoute(
name: "areaDefault",
template: "{area:exists}/{controller=Home}/{action=Main}/{id?}");
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Main}/{id?}/{exit?}");
});
}
Logs
dbug: Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionDispatcher[4]
Establishing new connection.
dbug: Microsoft.AspNetCore.SignalR.HubConnectionHandler[5]
OnConnectedAsync started.
dbug: Microsoft.AspNetCore.Http.Connections.Internal.Transports.WebSocketsTransport[1]
Socket opened using Sub-Protocol: '(null)'.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:5000/favicon.ico
info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[2]
Sending file. Request path: '/favicon.ico'. Physical path: 'D:\K4\KMS\KMS\bin\Release\netcoreapp2.2\publish\wwwroot\favicon.ico'
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 6.664ms 200 image/x-icon
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:5000/lib/Popper/popper.min.js.map
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 3.4573ms 404
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:5000/lib/bootstrap/dist/js/bootstrap.min.js.map
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:5000/lib/signalr/dist/browser/signalr.min.js.map
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 2.3443ms 404
info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[2]
Sending file. Request path: '/lib/bootstrap/dist/js/bootstrap.min.js.map'. Physical path: 'D:\K4\KMS\KMS\bin\Release\netcoreapp2.2\publish\wwwroot\lib\boo
tstrap\dist\js\bootstrap.min.js.map'
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 114.858ms 200 text/plain
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:5000/lib/bootstrap/dist/css/bootstrap.min.css.map
info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[2]
Sending file. Request path: '/lib/bootstrap/dist/css/bootstrap.min.css.map'. Physical path: 'D:\K4\KMS\KMS\bin\Release\netcoreapp2.2\publish\wwwroot\lib\b
ootstrap\dist\css\bootstrap.min.css.map'
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 18.0356ms 200 text/plain
dbug: Microsoft.AspNetCore.SignalR.HubConnectionContext[2]
Handshake was canceled.
dbug: Microsoft.AspNetCore.Http.Connections.Internal.Transports.WebSocketsTransport[7]
Waiting for the client to close the socket.
dbug: Microsoft.AspNetCore.Http.Connections.Internal.Transports.WebSocketsTransport[2]
Socket closed.
dbug: Microsoft.AspNetCore.Http.Connections.Internal.HttpConnectionManager[2]
Removing connection 8K2CDgDs6jWXM7DPMWk_Dg from the list of connections.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 15047.5227ms 101
JavaScript code which caught the exception.
function kmsEventExit(url) {
var exitButton = document.getElementById("exitButton");
var connection = new signalR.HubConnectionBuilder().withUrl(url + "/KmsHub").build();
//Disable send button until connection is established
exitButton.disabled = true;
//Wait until connection finishes.
connection.start().then(function () {
exitButton.disabled = false;
}).catch(function (err) {
return console.error(err.toString()); //WebSocket is not in the OPEN state
});
//Call ExitKms on clicking the button.
exitButton.addEventListener("click", function (event) {
connection.invoke("ExitKms").catch(function (err) {
return console.error(err.toString());
});
event.preventDefault();
});
//Catch the result.
connection.on("ExitKmsResult", function (isAlert, options) {
if (isAlert) {
swal(JSON.parse(options));
}
});
}
There has been an workaround posted in a GitHub Issue that has worked for me.
Before connecting, add:
Object.defineProperty(WebSocket, 'OPEN', { value: 1, });
Using this method, there's no need to remove pace.js.
Important note: if you are using Blazor Server, you will face the same issue. Remove pace.js then, as it's quite useless in this case.
I have identified the problem!
It did not work because pace.js was not compatible with signalr.js. WebSocket variable was duplicated in these two plugins. SignalR works fine after removing pace.js.
SignalR on VisualStudio worked with pace.js because it uses SSE and IIS Express, instead of WebSocket and Kestrel, thus pace.js and signalr.js can be compatible with this particular configuration.
Reference:
https://github.com/aspnet/SignalR/issues/2389
As Identified above, pace and signalr are not directly compatible, however putting the script below before loading pace.js will resolve the problem instead of outrightly remove pace.js
<script>
window.paceOptions = { ajax: { ignoreURLs: ['mainHub', '__browserLink', 'browserLinkSignalR'], trackWebSockets: false } }
</script>
Reference to above answer: https://stackoverflow.com/questions/54770354/how-to-use-asp-net-core-signalr-with-pace-js
The value of 'mainHub' is the signalR hub in your C# application you are connecting to.

webpack dev-server: Avoid proxy errors on HTTP errors returned from proxy target

I have a Vue.js project where I have configured a webpack dev-server to proxy all requests to the UI to my backend server. Here is the relevant part of vue.config.js:
devServer: {
contentBase: PATHS.build,
port: 9000,
https: false,
hot: true,
progress: true,
inline: true,
watchContentBase: true,
proxy: {
'^/': {
target: 'http://127.0.0.1:8089',
secure: false
},
}
},
I've noticed that if the HTTP response code from http://127.0.0.1:8089 is anything other than 2xx then the proxy fails with the following error:
Proxy error: Could not proxy request /api/test from localhost:9000 to http://127.0.0.1:8089.
See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (HPE_INVALID_CHUNK_SIZE).
This also causes the HTTP response code from the request to localhost:9000 to be 500 for any error and all the information about what went wrong on the server side is lost. This is problematic as I want to be able to extract information from error responses to display to the user.
I know it's possible to do because I had it working on an older Angular project which I think was using Webpack 3 (am now using Webpack 4). I tried copying all the dev-server config from this project but it just doesn't seem to work here!
EDIT: I was wrong. The Proxy error does not occur on every bad response but only for one of the requests which is a multipart file upload. Still unable to reproduce this in a smaller example to put on github though so struggling to pinpoint the cause.
This error message comes from node_modules/#vue/cli-service/lib/util/prepareProxy.js, which define a onError callback for node-http-proxy;
So I did some experiment, make back-end api generate 400 404 500 response, but I didn't got this error.
After I happen to close back-end api, error arise:
Proxy error: Could not proxy request /hello from localhost:8080 to http://localhost:8081 (ECONNREFUSED).
I search in the doc and find these:
The error event is emitted if the request to the target fail. We do not do any error handling of messages passed between client and proxy, and messages passed between proxy and target, so it is recommended that you listen on errors and handle them
So the onError do not handle error code, is called only when request fail (500 response is still treated as a complete request, connection refuse is not)
Go back to your error message, [HPE_INVALID_CHUNK_SIZE] means bad request to the back-end api. In this issue, it gives an solution: add a keep-alive header:
devServer: {
publicPath: 'http://localhost:9090/front/static-dev/build/',
port: 9090,
proxy: {
'/**': {
target: 'http://localhost:8080',
secure: false,
changeOrigin: true,
headers: {
Connection: 'keep-alive'
}
},
open: true
}
I have finally found the problem, and I apologise, it was a lot more of a specific issue than I originally thought when I wrote the question.
Issue was to do with a request which was proxied to another server using the Spring RestTemplate:
e.g.
#PostMapping("/upload")
public ResponseEntity upload(#RequestParam("file") MultipartFile file)
throws Exception {
String baseUrl = serviceProperties.getAddress();
HttpEntity<MultiValueMap<String, Object>> request = createMultipartRequest(file.getBytes());
return restTemplate.postForEntity(baseUrl + "/api/upload", filterRequest, String.class);
}
The ResponseEntity returning from the rest template proxy contained the header "Connection: close" when the response was anything other than 200 which cause the connection to close and caused this request to fail to return anything which subsequently made the dev-server proxy fail on the UI.
Fixed this by not passing the response headers from the rest template proxy to the response:
#PostMapping("/upload")
public ResponseEntity upload(#RequestParam("file") MultipartFile file)
throws Exception {
String baseUrl = serviceProperties.getAddress();
HttpEntity<MultiValueMap<String, Object>> request = createMultipartRequest(file.getBytes());
ResponseEntity response = restTemplate.postForEntity(baseUrl + "/api/upload", filterRequest, String.class);
return new ResponseEntity<>(response.getBody(), response.getStatusCode());
}

Handle unavailable server with vue-resource

Is there a way to handle errors with vue-resource when a HTTP response has not been received?
For example, when the backend server is unavailable (i.e. http://localhost:30000 doesn't exist) I receive the following error in Safari:
[Error] Failed to load resource: Could not connect to the server. (create, line 0)
However the vue-resource response object passed to the error callback is empty (doesn't give any indication about the failure to connect to the server):
{ "url": "http://localhost:30000", "ok": false, "status": 0, "statusText": "", "headers": { "map": { "": [ "" ] } }, "body": null }
What is the best way to handle this? Hardcoding for a status === 0 seems like it might be overly generic?