Traffic control for WMS - wms

I got a request from customer to create a service for traffic control of WMS service. The idea is:
a company buys some amount of data from WMS provider;
the company shares this data among its clients ;
the service should track how much traffic and requests have been consumed.
So I need some kind of proxy which passes requests to a target WMS services and meanwhile logs passed traffic.
The problem is that I have no clue how to start and where to start from. I will appreciate any idea, concept or so.
Thanks in advance!

Here is how I implemented proxy that passes requests to GeoServer WMS service and returns the map image. I use Web API, NET 4.5. You can customize my example with logging and authorization.
public async Task<HttpResponseMessage> GetMapAsync()
{
HttpClient client = new HttpClient();
WmsLayer layer = _unitOfWork.LayerRepository.GetById(model.LayerId) as WmsLayer;
// This is typical WMS request url pointing to server behind the firewall,
// something like http://localhost:8081/geoserver/data/wms?service=WMS&version=1.1.0&request=GetMap&layers=data:layer1&styles=&bbox=337098.1084,4972868.3433,368833.6,5014800.3417&width=387&height=512&srs=EPSG:3765&format=image%2Fpng%3B+mode%3D8bit
string url = layer.GetWmsRequestUrl(layer.Url, model.SRS, model.Width, model.Height, model.BBox);
// See http://developer.greenbutton.com/downloading-large-files-with-the-net-httpclient/
var responseMessage = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead);
var response = Request.CreateResponse();
response.Content = new PushStreamContent(
async (outputStream, httpContent, transportContext) =>
{
var buffer = new byte[65536];
using (var httpStream = await responseMessage.Content.ReadAsStreamAsync())
{
var bytesRead = 1;
while ((bytesRead = httpStream.Read(buffer, 0, buffer.Length)) > 0)
{
await outputStream.WriteAsync(buffer, 0, bytesRead);
}
}
outputStream.Close();
}
, new MediaTypeHeaderValue("image/png"));
return response;
}

Related

Use refresh token in Google's People API Client Library for .NET

I am rewriting an app that used Google Contacts API (RIP) to use People API. I already have a refresh token. Previously, I created an instance of the OAuth2Parameters object, and used it to create an instance of the RequestSettings class to be passed to the ContactsRequest constructor
OAuth2Parameters oparams = new OAuth2Parameters
{
AccessToken = tokenData.access_token,
RefreshToken = tokenData.refresh_token,
ClientId = ClientId,
ClientSecret = ClientSecret,
AccessType = "offline",
ApprovalPrompt = "force",
Scope = _contactScope
};
if (string.IsNullOrWhiteSpace(oparams.AccessToken))
{
oparams.AccessToken = "xyz"; //it doesn't matter what this token is, it just can't be blank, it will get refreshed
OAuthUtil.RefreshAccessToken(oparams);
dataStore._storedResponse.access_token = oparams.AccessToken;
}
var settings = new RequestSettings("My App")
{
OAuth2Parameters = oparams
};
if (paging)
{
settings.PageSize = 50;
settings.AutoPaging = true;
}
return new ContactsRequest(settings);
I cannot figure out how to do the same in the new world of People API. I obviously need to use PeopleServiceService object, but its constructor takes an instance of the Initializer object, and I don't know out how I can initialize it with the refresh token and (possibly) access token.
Here's the official tutorial on how to do authentication with the .NET library for all Google APIs:
https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth
Here's a useful snippet from it that will also help with persisting the refresh token to a file and use it in future authentication attempts:
UserCredential credential;
using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
{
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
new[] { BooksService.Scope.Books },
"user", CancellationToken.None, new FileDataStore("Books.ListMyLibrary"));
}
// Create the service.
var service = new BooksService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Books API Sample",
});
var bookshelves = await service.Mylibrary.Bookshelves.List().ExecuteAsync();

Blazor webassembly http default header Forge Design Automation

Good morning,
I am trying to develop a webapp using Blazor and Net5. I have successfully implemented the 3 legged authentication system and attached the token to the default header for further requests.
I have implemented also the 2 legged authentication request in the same process and saved both in the local storage.
Now I need to start to call some Data Management service to store and retrieve models and also submit work items to design automation. All of these will require to send the bearer token together with the request.
I would like to manage this bit of the application on the server side and the question is: is there a way to use the token on the server side other then just try to retrieve that from the local storage?
Also, is is possible to setup two different HttpClient in the client app to be able to attach two different tokens and then use the same http client in the server-side Blazor? I assume I can not inject a service from the client to the server thou.
I can easily do it in the client side using DI
public async Task<string> PostSignedUrlAsync(string bucketKey, string objectKey)
{
using (var client = new HttpClient())
{
var token = await tokenManager.GetTwoFactorAsync();
using (var request = new HttpRequestMessage(
HttpMethod.Post,
$"https://{configurationManager.Host}/oss/v2/buckets/{bucketKey}/objects/{objectKey}/signed"
)
)
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
using (var response = await client.SendAsync(request))
{
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<PostObjectSigned>(json).SignedUrl;
}
}
return null;
}
}
}
public async Task PostTwoFactorAsync()
{
using (var client = new HttpClient())
{
using (var request = new HttpRequestMessage(
HttpMethod.Post,
$"https://{configurationManager.Host}/authentication/v1/authenticate"
)
)
{
var body = $"client_id={configurationManager.ClientId}&client_secret={configurationManager.ClientSecret}&grant_type=client_credentials&scope={configurationManager.ScopesInternal}";
request.Content = new StringContent(body, Encoding.UTF8, "application/x-www-form-urlencoded");
using (var response = await client.SendAsync(request))
{
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
TokenInternal = JsonConvert.DeserializeObject<Token>(json);
TokenInternal.ExpiresOn = DateTime.UtcNow.AddSeconds(TokenInternal.ExpiresIn) - TimeSpan.FromMinutes(10);
await localStorage.SetItemAsync(configurationManager.LocalStorageKeyInternal, TokenInternal);
}
}
}
}
}
Maybe is a simple question with a simple answer but I can't find any example that can explain how to solve this "connection" and there are now example in the Forge documentation around Blazor implementation that are suitable for this task.
Thanks in advance
Firstly, please don't call APIs from client side, send the token with only scope: viewables:read for viewing in forge viewer. Other than this, call all the forge APIs from server side. This is for security reasons. Because if you send and store tokens to client side, it's easy to get access to your resources for any client.
Regarding token scopes please refer these links:
Documentation
Tutorial

Dart HttpServer Cache

I have Http server loading data from different server (through HttpClient). You can see the code here: Dart HTTP server and Futures
I am able to load response to JSON map and now I want to keep this map in memory until it's invalidated (I can get information on change way faster that whole set). What would be best way to save my JSON map to in memory object and retrieve it from memory until it needs to be refreshed?
Solved in comments above. Summary: if you need to keep value in very simple "cache" scenario, you can make a copy of the object and invalidate it by copying new values over.
main() {
Map cachedMap = new Map();
var lastCached = new DateTime.now();
final Duration cacheDuration = new Duration(minutes: 10);
HttpServer.bind(InternetAddress.ANY_IP_V4, 4040).then((HttpServer server) {
print('listening on localhost, port ${server.port}');
server.listen((HttpRequest request) {
var now = new DateTime.now();
if (lastCached.add(cacheDuration).isAfter(now) && cachedMap.isNotEmpty) {
handleMap(request, cachedMap);
} else {
//do something to fill map
}
;
});
}).catchError((e) => print(e.toString()));
}

How Upload Files on Server using WebClient Windows phone?

I want upload a file (any type) on a server.
I have my file which is saved like this (I use FileAssociation)
await SharedStorageAccessManager.CopySharedFileAsync(ApplicationData.Current.LocalFolder, "fileToSave" + fileext, NameCollisionOption.ReplaceExisting, NavigationContext.QueryString["filetoken"]);
Then I get the saved file
StorageFolder folder = ApplicationData.Current.LocalFolder;
var file = await folder.GetFileAsync("fileToSave" + fileext);
Stream data = Application.GetResourceStream(new Uri(file.Path, UriKind.Relative)).Stream;
string filename = System.IO.Path.GetFileName(file.Path);
ServerFunctions.UploadFile(filename,data);
Then I start the Upload
internal void UploadFile(string fileName,Stream data)
{
WebClient web = new WebClient();
if (!string.IsNullOrEmpty(dataRequestParam.AuthentificationLogin))
{
System.Net.NetworkCredential account = new NetworkCredential(dataRequestParam.AuthentificationLogin, dataRequestParam.AuthentificationPassword);
web.Credentials = account;
}
web.AllowReadStreamBuffering = true;
web.AllowWriteStreamBuffering = true;
web.OpenWriteCompleted += (sender, e) =>
{
PushData(data, e.Result);
e.Result.Close();
data.Close();
};
web.OpenWriteAsync(dataRequestParam.TargetUri,"POST");
}
private void PushData(Stream input, Stream output)
{
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) != 0)
{
output.Write(buffer, 0, bytesRead);
}
}
The web server is supposed to send me as a response a xml with an error code or succes code inside.
None error is thrown but it doesnt work.And I don't understand why the e.result is a stream object. As I said the server should return a string...(xml file)
Could you bring me some explannations of what is happening in my code and if it will work with all types of files ?
Thanks
I think part of the problem here is that you're attempting to get this to behave like a streaming protocol when it seems you intend a request/response type architecture. For those purposes, you should consider working with a WebRequest object.
Bear with me as I fully qualify the namespace of the objects used inline, so it may get a little verbose, but I want you to know where to find these things.
internal async void UploadFile(string fileName, System.IO.Stream data)
{
// Specify URI, method, and credentials for the request
System.Net.WebRequest web = System.Net.HttpWebRequest.CreateHttp(dataRequestParam.TargetUri);
web.Method = "POST";
if (!string.IsNullOrEmpty(dataRequestParam.AuthenticationLogin))
{
web.Credentials = new System.Net.NetworkCredential(dataRequestParam.AuthenticationLogin, dataRequestParam.AuthenticationPassword);
}
// Create the request payload from the provided stream
System.IO.Stream requestStream =
await System.Threading.Tasks.Task<System.IO.Stream>.Factory.FromAsync(web.BeginGetRequestStream, web.EndGetRequestStream, null);
await data.CopyToAsync(requestStream);
// Get a response from the server
System.Net.WebResponse response =
await System.Threading.Tasks.Task<System.Net.WebResponse>.Factory.FromAsync(web.BeginGetResponse, web.EndGetResponse, null);
// Possibly parse the response with an XmlReader (example only)
System.Xml.XmlReader reader = System.Xml.XmlReader.Create(response.GetResponseStream());
string responseText = reader.ReadInnerXml(); // TODO: Real work here
}
The one oddity here is using the Task factory to create a task from the begin and end methods from getting both the request stream and the response. This makes it much simpler to consume these methods as you get a Task back which can be awaited for its return object, which you can then manipulate directly.
I'm not sure what form your response from the server takes on success versus failure, so I've simply shown how to create an XML reader to parse XML from the resulting stream. You can do whatever parsing is necessary yourself on these lines, but this should at least give you a look at what your server is returning in response.
The final code I use.
WebRequest web = HttpWebRequest.CreateHttp(dataRequestParam.TargetUri);
web.ContentType = dataRequestParam.ContentType;
web.Method = "POST";
web.ContentLength = data.Length;
if (!string.IsNullOrEmpty(dataRequestParam.AuthentificationLogin))
{
web.Credentials = new NetworkCredential(dataRequestParam.AuthentificationLogin, dataRequestParam.AuthentificationPassword);
}
using (var requestStream = await Task<Stream>.Factory.FromAsync(web.BeginGetRequestStream, web.EndGetRequestStream, web))
{
await data.CopyToAsync(requestStream);
}
WebResponse responseObject = await Task<WebResponse>.Factory.FromAsync(web.BeginGetResponse, web.EndGetResponse, web);
var responseStream = responseObject.GetResponseStream();
var sr = new StreamReader(responseStream);
string received = await sr.ReadToEndAsync();
return received;
}

Reading the content of HTTP Stream before the Content stream is Complete Windows Phone 8

I am trying to get a reference to a response stream before its complete in windows phone 8.
In other .Net platforms you can do
HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(myUri);
WebResponse subscribeWebResponse = null;
Stream subscribeStream = null;
subscribeWebResponse = httpRequest.GetResponse();
subscribeStream = subscribeWebResponse.GetResponseStream();
For the purpose of creating Portable class libraries I've used the HttpClientLibrary from nuget.
This Adds ref to extensions assembly Microsoft.Net.Http
this allows me to return the async request at the time the headers have been read instead of waiting for the content transfer to be complete with
var clientResponse = await httpClient.SendAsync(requestmessage, HttpCompletionOption.ResponseHeadersRead);
The problem I'm having is that in windows phone 8 it doesn't work correctly, and still awaits the completion of the content stream to return.
Additionally
await httpWebRequest.BeginGetResponse(callback, request)
has the same behavior as these async methods are actually waiting for the completion of the web's response to continue execution.
So, is there any way to achieve the returning the response/stream at the point that i have received the response headers without Microsoft.Http.Net package?
Even if it has to be a Windows Phone 8 Platform Specific Solution?
Possibly an extension of HttpWebRequest?
From what I can tell, ResponseHeadersRead works on the WP8 emulator as it does on the desktop.
I installed the Win8 SDK. Created a windows phone app. I added this code to the MainPage ctor. This demonstrates a very rudimentary long polling example.
var client = new HttpClient();
var request = new HttpRequestMessage()
{
RequestUri = new Uri("http://oak:1001/longpolling")
};
client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, new CancellationToken())
.ContinueWith((t) =>
{
var response = t.Result;
response.Content.ReadAsStreamAsync()
.ContinueWith(s =>
{
var st = s.Result;
while (true)
{
var message= ReadNextMessage(st);
}
});
});
}
private static string ReadNextMessage(Stream stream)
{
int chr = 0;
string output = "";
while (chr != 10)
{
chr = stream.ReadByte();
output += Convert.ToChar(chr);
}
return output;
}
On my host dev machine I have a web api with a controller that looks like this...
public class LongPollingController : ApiController
{
public HttpResponseMessage Get()
{
Thread.Sleep(2000);
var content = new PushStreamContent( (s,c,t) =>
{
int i = 0;
while (true)
{
try
{
var message = String.Format("The current count is {0} " + Environment.NewLine, i++);
var buffer = Encoding.UTF8.GetBytes(message);
s.Write(buffer, 0, buffer.Length);
}
catch (IOException exception)
{
s.Close();
return;
}
Thread.Sleep(1000);
}
});
return new HttpResponseMessage(HttpStatusCode.OK)
{
RequestMessage = Request,
Content = content
};
}
}
So here's the deal. I would say that what you want to do is not possible, due to platform limitations... But SignalR has a WP client and is able to manage it. So it seems to me you have two options:
1) Dig into the SignalR source code to see how they do it (I'm on my phone right now so I can't provide a link).
UPDATE: Here is the link. They do some pretty neat tricks, like setting the Timeout to -1 for long-running clients. I think you should definitely use the techniques here.
OR
2) You can move whatever you're doing over to SignalR, which would gain the benefit of having a robust infrastructure and being cross-platform compatible.
HTH