Set the dart-editor server responses - dart

My apache server is setup to respond to any request with the index.html. The idea behind this is to let the web app we are creating handle the routing. The dart-editor test environment does not do this by default.
Instead when i go to http://127.0.0.1.8080/something/that/does/not/exisit it will return a 404. I would like it to respond with the index.html and let the app handle the routing.
Is it possible to setup this behaviour for the dart test environment?

The suggested way is to use a custom server that acts as a proxy that forwards to pub serve.
see also
https://code.google.com/p/dart/issues/detail?id=20432
The code (copied from the linked issue)
Future proxyToPub(HttpRequest request, String path) {
const RESPONSE_HEADERS = const [
HttpHeaders.CONTENT_LENGTH,
HttpHeaders.CONTENT_TYPE ];
var uri = pubServeUrl.resolve(path);
return client.openUrl(request.method, uri)
.then((proxyRequest) {
proxyRequest.headers.removeAll(HttpHeaders.ACCEPT_ENCODING);
return proxyRequest.close();
})
.then((proxyResponse) {
proxyResponse.headers.forEach((name, values) {
if (RESPONSE_HEADERS.contains(name)) {
request.response.headers.set(name, values);
}
});
request.response.statusCode = proxyResponse.statusCode;
request.response.reasonPhrase = proxyResponse.reasonPhrase;
return proxyResponse.pipe(request.response);
})
.catchError((e) {
print("Unable to connect to 'pub serve' for '${request.uri}': $e");
var error = new AssetError(
"Unable to connect to 'pub serve' for '${request.uri}': $e");
return new Future.error(error);
});
}
I use the route_hierarchical package in a way that it works the same with usePushState enabled or disabled. This way I can use URL fragments for development and pushState for deployment.
See https://stackoverflow.com/a/25256858/217408
or the two similar (simple) examples where one uses usePushState false and the other true https://github.com/bwu-dart/bwu_polymer_routing

Related

How do I setup Swashbuckle v5 with swagger when I have a custom base url?

I am upgrading a .net API to .net Core 3.1 and using Swashbuckle.AspNetcore 5.4.1. The API is running inside a ServiceFabric app. I found this https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/1173 and tried to follow that and swagger gets generated but if I try to use the Swagger UI to send requests the request URL is with the wrong IP so the request fail.
In the old Swashbuckle 4.0.1 setup we did not specify host, only the relative basePath. How can I achieve the same?
Startup.cs
var swaggerBasePath = "/MySfApp/SfApp.ClientApi/";
app.UseSwagger(c =>
{
c.SerializeAsV2 = serializeAsSwaggerV2;
c.RouteTemplate = "swagger/{documentName}/swagger.json";
c.PreSerializeFilters.Add((swaggerDoc, httpReq) =>
{
swaggerDoc.Servers = new List<OpenApiServer> { new OpenApiServer { Url = $"{httpReq.Scheme}://{httpReq.Host.Value}{swaggerBasePath}" } };
});
});
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("api/swagger.json", "My API V1");
});
The result is that the Swagger UI loads correctly on URL:
http://145.12.23.1:54000/MySfApp/SfApp.ClientApi/swagger/index.html
and it says under name that BaseUrl is:
[ Base URL: 10.0.0.4:10680/MySfApp/SfApp.ClientApi/ ]
The 10.0.0.4:10680 is the node inside the ServiceFabric cluster. Correct IP to reach from outside is 145.12.23.1:54000. In the older version (4.0.1) of Swashbuckle it says baseUrl without IP first: "/MySfApp/SfApp.ClientApi"
Swagger.json is located at:
http://40.68.213.118:19081/MySfApp/SfApp.ClientApi/swagger/api/swagger.json
and it says:
"swagger": "2.0",
...
"host": "10.0.0.4:10680",
"basePath": "/MySfApp/SfApp.ClientApi/",
"schemes": [
"http"
],
"paths": {
"/activity/{activityId}": {
"get"
...etc
If i try to send a GET request from the Swagger UI the request is sent to wrong IP:
curl -X GET "http://10.0.0.4:10680/MySfApp/MySfApp/activity/3443"
EDIT 1:
After some digging I have now changed the setup to this in
startup.cs
var swaggerBasePath = "/MySfApp/SfApp.ClientApi/";
app.UsePathBase($"/{swaggerBasePath}");
app.UseMvc();
app.UseSwagger(c =>
{
c.SerializeAsV2 = serializeAsSwaggerV2;
c.PreSerializeFilters.Add((swaggerDoc, httpReq) =>
{
if (!httpReq.Headers.ContainsKey("X-Original-Host"))
return;
var serverUrl = $"{httpReq.Headers["X-Original-Proto"]}://" +
$"{httpReq.Headers["X-Original-Host"]}/" +
$"{httpReq.Headers["X-Original-Prefix"]}";
swaggerDoc.Servers = new List<OpenApiServer>()
{
new OpenApiServer { Url = serverUrl }
};
});
});
app.UseSwaggerUI(options => {
options.SwaggerEndpoint("api/swagger.json", "My API V1");
});
This now leads to the Swagger UI loading properly with the baseUrl
http://145.12.23.1:54000/MySfApp/SfApp.ClientApi/swagger/index.html
and also swagger.json is served correctly with the correct baseUrl.
http://145.12.23.1:54000/MySfApp/SfApp.ClientApi/swagger/api/swagger.json
So the wrong hostname is resolved. Thanks to idea from this thread.
However when I try to call an endpoint from the Swagger UI page, the curl URL does not include the baseUrl. So closer... but currently not possible to use Swagger UI.
curl -X GET "http://10.0.0.4:10680/activity/3443"
The swagger.json does not have 'host' nor 'basePath' defined.
We're using Swashbuckle version 6.1.4 - which is the latest as of this time of writing and we're still having the same issue when our API is deployed in Azure App Service that is mapped through Azure Front Door and APIM. The "Try out" functionality does not work as the base path / api route prefix is stripped from the Swagger UI. For example,
Instead of https://{DOMAIN}.com/{BASEPATH}/v1/Foo, the Swagger UI uses this: https://{DOMAIN}.com/v1/Foo. You can see that the /BASEPATH is missing.
I spent the whole day trying to fix this with trial and error, trying various approaches with no luck, I couldn't get an elegant way to get the base path from swagger configuration. For the time being, here's what I did to fix it:
app.UseSwagger(options =>
{
//Workaround to use the Swagger UI "Try Out" functionality when deployed behind a reverse proxy (APIM) with API prefix /sub context configured
options.PreSerializeFilters.Add((swagger, httpReq) =>
{
if (httpReq.Headers.ContainsKey("X-Forwarded-Host"))
{
//The httpReq.PathBase and httpReq.Headers["X-Forwarded-Prefix"] is what we need to get the base path.
//For some reason, they returning as null/blank. Perhaps this has something to do with how the proxy is configured which we don't have control.
//For the time being, the base path is manually set here that corresponds to the APIM API Url Prefix.
//In this case we set it to 'sample-app'.
var basePath = "sample-app"
var serverUrl = $"{httpReq.Scheme}://{httpReq.Headers["X-Forwarded-Host"]}/{basePath}";
swagger.Servers = new List<OpenApiServer> { new OpenApiServer { Url = serverUrl } };
}
});
})
.UseSwaggerUI(options =>
{
options.RoutePrefix = string.Empty;
options.SwaggerEndpoint("swagger/v1/swagger.json", "My Api (v1)");
});
Here's an open discussion related to this issue here.
I were having something similar in my solution and I have used a little bit this way and that works well for me, in case that helps someone.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
var pathBase = Configuration["PATH_BASE"];
if (!string.IsNullOrWhiteSpace(pathBase))
{
app.UsePathBase($"/{pathBase.TrimStart('/')}");
app.Use((context, next) =>
{
context.Request.PathBase = new PathString($"/{pathBase.TrimStart('/')}");
return next();
});
if (env.IsDevelopment())
{
app.UseSwagger(c =>
{
c.PreSerializeFilters.Add((swaggerDoc, httpReq) =>
{
if (!httpReq.Headers.ContainsKey("X-Original-Host"))
return;
var serverUrl = $"{httpReq.Headers["X-Original-Proto"]}://" + $"{httpReq.Headers["X-Original-Host"]}/" + $"{httpReq.Headers["X-Original-Prefix"]}";
swaggerDoc.Servers = new List<OpenApiServer>()
{
new OpenApiServer { Url = serverUrl }
}
});
});
app.UseSwaggerUI(c => c.SwaggerEndpoint($"/{pathBase.TrimStart('/')}/swagger/v1/swagger.json", "My.API v1"));
}
}
}
check the last line
app.UseSwaggerUI(c => c.SwaggerEndpoint($"/{pathBase.TrimStart('/')}/swagger/v1/swagger.json", "My.API v1"));
Try this:
serverUrl = $"{httpReq.Headers["X-Forwarded-Proto"]}://" +
$"{httpReq.Headers["X-Forwarded-Host"]}" + _basePath;
where _basePath can be set using the ServiceName property of StatelessServiceContext.
Please be noted that the original value of X-Forwarded-Proto may be overridden by SF.

ActiveMQ test connection

I am trying to test ActiveMQ connection and return a value. it crashes on line:
httpResponse = client.execute(theHttpGet);
It is not my code I am trying to debug it. Can anyone help me to understand why the code is using HttpGet?
public ActivemqBrokerInfo(String serverAddress, int port, String apiUrl, int timeout) {
// Default Activemq location
this.serverAddress = String.format("http://%s:%s/%s", serverAddress, port, apiUrl);
int timeoutInMs = timeout;
HttpClientBuilder builder = HttpClientBuilder.create();
RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(timeoutInMs).build();
builder.setDefaultRequestConfig(requestConfig);
client = builder.build();
}
public ActivemqBrokerInfo(String serverAddress) {
this(serverAddress, DEFAULT_PORT, DEFAULT_API_URL, DEFAULT_TIMEOUT);
}
#Override
public boolean testConnection() {
HttpGet theHttpGet = new HttpGet(serverAddress);
theHttpGet.addHeader("test-header-name", "test-header-value");
HttpResponse httpResponse = null;
try{
httpResponse = client.execute(theHttpGet);// Code is crashing on this line
} catch (IOException ex){
LOGGER.error("Broker down: ", ex);
}
return httpResponse != null;
}
When ActiveMQ runs is normally starts an embedded web server. This web server is used to host the web admin console as well as the Jolokia endpoint which acts as an HTTP facade in front of the broker's MBeans. In other words, any client can send HTTP requests to specially formed URLs on the broker to get results from the underlying management beans. This is exactly what your bit of code appears to be doing. It appears to be sending an HTTP request to the Jolokia endpoint (i.e. api/jolokia) in order to determine if the broker is alive or not.
Based on the information provided it is impossible to determine why testConnection() is not returning successfully since you've included no information about the configuration or state of the broker.
I recommend you add additional logging to see what may be happening and also catch Exception rather than just IOException.

How do I get webpack-dev-server to accept POST requests

In my project I call:
$ webpack-dev-server --history-api-fallback
And it starts an express server (I'm assuming) available on localhost:8080.
It works great except that I want to submit a form via POST into an iframe loading my app; localhost:8080 in development and something else in production.
I don't expect to do anything with that POST data in development, but in production, it needs to be POST.
When I try to use POST however, it cannot find POST /
Is there a configuration option or some other solution that will allow me to use the webpack-dev-server? (I really don't want to have to write my own server for this).
#cowCrazy had half of the story, but didn't show how to respond with the same response for GET in the case of POST, which is what I was looking for.
In the Webpack config, you do this:
module.exports = {
...,
devServer: {
setup(app) {
app.post('*', (req, res) => {
res.redirect(req.originalUrl);
});
},
}
}
This will just take the POST URL and redirect with the same URL, making it a GET request.
Instead of having a server error, it will redirect with GET.
What you are looking for is devServer. Bellow you can see my config for it. Under setup(app) you can add "almost" whatever you want:
module.exports = {
...,
devServer: {
inline: true,
port: 3000,
publicPath: '/',
setup(app){
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.get("/get/some-data", function(req, res){
console.log(req);
res.send("GET res sent from webpack dev server")
})
app.post("/post/some-data", bodyParser.json(), function(req, res){
console.log(req.body);
res.send("POST res sent from webpack dev server")
})
}
}
}
EDIT:
I have pushed a minimalistic example to github if you wanna take a better look.
Check if it solves your problem by converting the POST request to GET request:
bypass: function (req, res, proxyOptions) {
const url = req.url;
req.method = 'GET';
if (url.indexOf('?') > -1) {
return url.replace('?', '.json?');
} else {
return url + '.json';
}
}

In dart httpRequest getstring always error

I established a RESTful server, and I can get a simple string with my Chrome or IE using this URL: "http://localhost:8080/WebService/RESTful/getString"
But when using Dart, it always returns a error message:
"[object XMLHttpRequestProgressEvent]"
From the onError() callback method,
I'm sure that server returns a string with "text/plain" MIME type in Java.
Here is the code:
import 'dart:html';
void main() {
HtmlElement btn = document.body.querySelector("#btn");
btn.onClick.listen(onClick);
}
void onClick(Event v) {
var url = "http://localhost:8080/WebService/RESTful/getString";
HttpRequest.getString(url).then((str) {
window.alert(str.toString());
}, onError: (e) {
window.alert(e);
});
}
Who can help me ?
If you try to fetch resources from another server than the one your page was loaded from, this server needs to return CORS headers otherwise your browser refuses to fetch form this other server.
It depends on your server how this can be configured or added.
See for example
- How do you add CORS headers in Redstone interceptor?
- CORS with Dart, how do I get it to work?

how to run a polymer app via "Run in Dartium" from console?

I want to call a polymer webapp directly via command line or via 'Process' in a dart file.
I know when running it via the dart editor, a server on port 8080 is created and listening to requests for the /web folder.
but when launching
dartium/chrome.exe path/To/Index.html
from console its simply loading the files inside the browser but wont start a server for the client.
via
file:://path/to/file.html [no 'dart is not runnning' warning, but no polymer content]
or
127.x.x.x.x.x.x.x.x:xxxxxxxx/app/index.html will obviously tell me
'This webpage is not available'
DartEditor lauches pub serve. You can do this manually without Darteditor (since Dart 1.5 AFAIK). Just launch
pub serve
from within your Polymer app package directory.
Inside your console app launch the browser with the URL that loads the page from this server.
You could also include web server functionality into your console application that serves the Polymer app to your browser.
pub help serve
lists the available options.
You can try this script as an example how to call a polymer webapp directly via 'Process' in a dart file.
This example also includes launch of default browser.
import "dart:async";
import "dart:io";
import "package:path/path.dart" as pathos;
void main(List<String> args) {
String app;
String file;
switch (args.length) {
case 1:
app = args[0];
break;
case 2:
app = args[0];
file = args[1];
break;
default:
print("Usage: pubserve.dart app_path [file_name]");
exit(0);
}
if(!new Directory(app).existsSync()) {
print("Directory not exists: $app");
exit(-1);
}
pubServe(app, file).then((exitCode) {
exit(exitCode);
});
}
Future<int> pubServe(String app, String file) {
var sdk = Platform.environment["DART_SDK"];
if (sdk == null) {
print("Dart SDK not found");
return new Future(() => -1);
}
var executable = pathos.join(sdk, "bin", "pub");
var pattern = r"^Serving (?:.*) web on (.*)$";
var regexp = new RegExp(pattern);
return Process.start(executable, ["serve"], runInShell: true,
workingDirectory: app).then((process) {
process.stdout.listen((data) {
var string = new String.fromCharCodes(data);
for (var c in data) {
stdout.writeCharCode(c);
}
var match = regexp.matchAsPrefix(string);
if (match != null) {
var url = match.group(1);
if (file != null) {
url += "/$file";
}
Timer.run(() => runBrowser(url));
}
});
process.stderr.pipe(stderr);
stdin.pipe(process.stdin);
return process.exitCode.then((exitCode) {
return exitCode;
});
});
}
void runBrowser(String url) {
var fail = false;
switch (Platform.operatingSystem) {
case "linux":
Process.run("x-www-browser", [url]);
break;
case "macos":
Process.run("open", [url]);
break;
case "windows":
Process.run("explorer", [url]);
break;
default:
fail = true;
break;
}
if (!fail) {
//print("Start browsing...");
}
}
P.S.
NOTE:
If you run this script from Dart Editor, Editor will never stops execution of subprocess (pub serve in our case) when you stop current script in Dart Editor.
This is not related only to this script. Editor always keep subprocesses alive.
If you run it from cmd-line it terminates pub serve correctly.

Resources