scottoffen / grapevine-legacy Goto Github PK
View Code? Open in Web Editor NEWEmbedding A REST Server In Your Application Should Be Simple
Home Page: http://scottoffen.github.io/grapevine-legacy/
License: Apache License 2.0
Embedding A REST Server In Your Application Should Be Simple
Home Page: http://scottoffen.github.io/grapevine-legacy/
License: Apache License 2.0
What about support for PATCH, COPY, HEAD, OPTIONS, LINK, UNLINK, PURGE, LOCK, UNLOCK and PROPFIND?
Add the ability to segregate code by resource in separate classes using custom attributes and component model composition
There is a NullReference exception when requesting an http server using RestClient that times out or it is unreachable.
The problem is found on RestClient.cs on method Execute.
try
{
httpresponse = (HttpWebResponse)client.GetResponse();
}
catch (WebException e)
{
httpresponse = (HttpWebResponse)e.Response;
error = e.Message;
errorStatus = e.Status;
}
When there is a timeout, a WebException is raised indicating a timeout. The problem is that the property Response of that object is null. Then, when creating the RestResponse object a couple of lines later, it fails.
var response = new RestResponse(httpresponse, stopwatch.ElapsedMilliseconds, error, errorStatus);
Because you can not call the method GetResponseStream on a null object. This is the first line of the RestResponse constructor:
StreamReader reader = new StreamReader(response.GetResponseStream());
See Punit Ganshani's article on 5 steps to targeting multiple .NET frameworks and Microsoft's Framework Design Guidelines.
I would like to specify a base path that is appended to the base url which would provide a way to define separate service endpoints on my server with different implementations that are separated by RESTScope. Right now i would have to hardcode this in every RESTRoute regex attribute.
[RESTScope(BasePath="myServiceBasePath"]
I tried to implement custom route exception handling by overriding the method InternalServerError
in my implementation of RESTResource
.
My override is never invoked when deliberately throwing an Exception in my route handler method.
I tracked the issue down to the finally block of the ProcessRequest()-method.
As I see it, the methods InternalServerError()
and NotFound()
should be executed on route
.
If I'm right I can provide a pull-request.
String extension methods defined in Grapevine are accessible to the assemblies that reference it. This is impolite of me. I must not allow my syntactic sugar to bleed into other environments.
Need to implement a REST Client to facilitate initializing REST requests.
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.NullReferenceException: Object reference not set to an instance of an object
at Grapevine.Client.RESTRequest.set_Resource (System.String value) [0x00000] in <filename unknown>:0
at Grapevine.Client.RESTRequest..ctor (System.String resource, HttpMethod method, ContentType type, Int32 timeout, System.Text.Encoding encoding) [0x00000] in <filename unknown>:0
This happens no matter what is set in the constructor for RESTRequest, both with nothing set and also with the Resource set. It's caused by _parameters being null so it cannot be cleared. I'd PR it but my fork has reformatted everything thanks to MonoDev.
I'd like to introduce a middleware concept to Grapevine. The goals are:
Everyone who has used expressJS knows what I'm talking about. You can read about the concept here: http://expressjs.com/guide/using-middleware.html
The gist is, that there is not one route handler but there can be multiple route handlers for a request and if a route handler decides to answer a request he can do so. But he can also decide to pass the handling to the next route handler of the ones that match the route regex. This enables to have e.g. authentication checks of several different routes to be handled in one place.
To make it happen there are a few things that need to be done:
Please comment if you think that this should be part of grapevine or if you think that it is not needed. Cheers :)
Based on this StackOverflow answer, so that getting parameters from the query string of the request can be done in RESTRoute
s like this:
int id = context.Request.QueryString.GetValue<int>("id");
DateTime date = context.Request.QueryString.GetValue<DateTime>("date");
If the host is not reachable the following lines result in an ArgumentNullException:
var client = new RESTClient("http://localhost:4444");
var request = new RESTRequest("test");
var response = client.Execute(request);
The Message itself says: The value must not be null. Paramater name: cookies
The error is misleading, it should say that the host was not reachable.
What is the appropriate way to communicate application-specific information from the program that starts the server to the request handlers? I'm currently putting that information into static properties of the sealed class that derives from RESTResource, because, unless I've missed it, the program that starts the server has no control over the lifecyle of the instance(s) of that class that are created by the server. Static properties suffice for now, but that approach could complicate things if one needs to start multiple servers. Would you consider allowing user code to instantiate these instances and pass them to the server in the configuration object?
Add Dynamic property to RestServer class
Ok, this might rather be a issue in the documentation than in the code, but anyway ...
Using the suggested ...
[RESTRoute(Method = HttpMethod.DELETE, PathInfo = @"^/shutdown$")]
public void HandleShutDownRequests(HttpListenerContext context)
{
this.SendTextResponse(context, "shutting down");
this.Server.Stop();
}
to remotely shutdown the Server does not work for me. If I use it as suggested, I get a deadlock in the RestServer.Stop() method, which does not surprise me because of the
foreach (Thread worker in this._workers)
{
worker.Join();
}
that can be found there. The RESTRoute that invoked the stop uses one of these workers, doesn't it?
So, I'm using this instead:
[RESTRoute(Method = HttpMethod.GET, PathInfo = @"^/exit$")]
public void HandleShutDownRequests(HttpListenerContext context)
{
this.SendTextResponse(context, "shutting down");
// create a new thread that will kill the server asynchronously
(new Thread(() => Server.Stop() )).Start();
}
PS: Thanks for making this available!
Hi!
Putting 0.0.0.0 in the RestServer config, generate an exception on windows 7 64 bit
Regards
How to implement a basic auth system in the RestServer?
Rather than simply returning the text of the error code, add a mechanism whereby a custom response body can be attached to a particular HttpStatusCode
, such that the developer only has to make a single call and the custom response will be sent instead of the default one.
Ideas
HttpContext
and an optional HttpStatusCode
I've received several requests for examples/documentation in different languages.
I expect there will be more in the future. As I don't know these language, if anyone wants to help me with this, many people would be grateful to you.
title is wrong (can I change that?) there is an exception but Message is not the issue. Not sure why ExceptionToString is throwing, but you wouldn't think it would, would you?
[update] ExceptionToString is throwing because trace.GetFrame(2) is returning null. Because the stack isn't that deep. :)
Proposal 2 still valid: in RESTServer.ProcessRequest, wrap the finally{} block's error handler in a try/finally block to ensure that ctx.Response.Close() and ctx.Close() are always called out of paranoia. (In fact may want to add a second block around the whole function.) Also might want a top level exception handler that tries to use Close(byte[]) to send a generic "something is dreadfully wrong" response.
And don't fall behind again!
I'm of the opinion that routes should not take GET parameters into consideration when matching. Currently, the PathInfo
is checked against RawUrl
which includes GET parameters. This makes it hard to write effective routes, because order of parameters matter.
My routes are all starting to take this kind of shape, especially since they will be used in JSONP calls:
[RESTRoute(Method = HttpMethod.GET, PathInfo = @"^/poll/(\?[^/]*)?$")]
If users need to use GET parameters, then they should be extracted from within the route handler and validated there. NotFound
can be returned on missing parameters.
Unfortunately, there aren't any properties that I can find on context.Request
that expose just the path
portion of the URL. If this is accepted, I'd probably split on ?
and take the first match.
Note that I'm actually using GrapevinePlus (great work by the way), but I figured that issues relating to both should be raised here.
Thanks.
I find myself re-matching path parts in my handlers. I am considering modifying the RESTServer to pass any matches from its regex match (PathInfo) as an optional extra parameter to the handler. Does this seem desirable?
The more complicated part of this is backward compatibilty, so it would need to detect the method signature, as I am pretty sure Invoke() will barf if the array size does not match the invoked method signature.
The obvious solution is something like like void MyGetHandler( HttpListenerContext ctx, string [] matches ) or similar. Other options include:
Just a thought. it just irks me to write my patterns twice. It also irks me to see 50-odd regex patterns recompiled on every http request, but that's for another issue I guess. :)
Here is an example: most of my handlers look like this:
static readonly Regex GetSomethingStatusParams =
new Regex( @"^/api/something/(?<id>[^/]*)/status" );
[RESTRoute(Method = HttpMethod.GET,
PathInfo = @"^/api/something/([^/]*)/status$")]
public void HttpGetSomethingStatus( HttpListenerContext ctx )
{
// UrlMatcher throws rest specific exceptions on failure for convenience...
UrlMatcher matcher = new UrlMatcher( GetSomethingStatusParams, ctx.Request.RawUrl );
SendJsonResponse( ctx, GetSomethingStatus( matcher.GetLong( "id" ) ) );
}
Which is a bit cumbersome. The Server could, say, check whether (MethodInfo.Parameters.Length > 1), and if so, pass the match from the regex into the function, leading to something along the lines of:
[RESTRoute(Method = HttpMethod.GET, PathInfo = @"^/api/something/(<id>[^/]*)/status$")]
public void HttpGetSomethingStatus( HttpListenerContext ctx, Match urlMatch )
{
long id = _ConvertToLong( urlMatch.Groups["id"].Value );
SendJsonResponse( ctx, GetSomethingStatus( id );
Should be doable, prevents multiply-typing patterns, etc. Desirable?
...Another quick update: I have implemented this--it's pretty simple really. I want to clean up the implementation and add tests (how do I run these on mono!?). Also I made it against GrapevinePlus (oops) and need to.. backport? upport? sideport it? It would be pretty simple to do magic "name matching" like WebApi and other apis do, but personally I think just returning the matching Match is more flexible, simple, and fits with the whole "simple" approach of Grapevine.
First, thanks for library.
I have lost however some time before I found some really annoying issue.
I wanted to test Grapevine library and created a project which I called... GrapevineTest. Not very original, isn't it?
When I tried to add my own code for REST incoming messages it didn't work. I used your example and it didn't work:
[RESTRoute(Method = HttpMethod.GET)]
public void HandleAllGetRequests(HttpListenerContext context)
{
this.SendTextResponse(context, "GET is a success!");
}
After a long search and being completely stupid why it doesn't work I found this:
private Dictionary<string, RESTResource> LoadRestResources()
{
....
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
if (assembly.FullName.Matches(@"^(microsoft|mscorlib|vshost|system|grapevine)")) { continue; }
For my project assembly.FullName was GrapevineTest so the library skipped it. When I renamed my project it began to work.
Not a big problem, but I'd like to warn the others :)
Hi, It's a great library to have slim web server on any machine.
When I try to dispose all the resources that I use including RESTServer I get the below exception
"The I/O operation has been aborted because of either a thread exit or an application request"
Just create a simple console with the below lines, please turn on the CLR exception
RESTServer server = Init(8008, "sampleapi");
server.Start();
Console.ReadLine();
server.Dispose();
I tried few options before submitting this request the exception still occurs.
Many thanks
The content-types.json file is used to determine the correct MIMEType to use when passing a file back, based on an examination of the file extension.
Yesterday I had a problem which took a while to figure out:
var server = new RESTServer();
server.Start();
We didn't fire it up with admin privileges so the HttpListener throw an exception. We had no clue it did until we debugged inside the Grapevine start method.
I think an exception which prevented the server start should in no case be swallowed because the user of the library is the one who has to handle this not the library itself.
Of course there is a logger so if this is turned on at least something is visible. But how should an application relying on the server listening should handle the event where the server is NOT running because an exception was thrown?
At the very least there should be the possibility to pass an action that is executed with the exception is parameter to indicate the failure of the failed attempt to start the server. Otherwise there is no proper way for the application to handle the failure.
I also am aware of the possibility to check the IsListening
-property but this is not giving access to the exception which I might want to have.
What were you thinking? Responder is technically accurate but confusing! Change it to Handler.
Also, update documentation to reflect this change.
[RESTScope(BaseUrl = "http://localhost:1111")]
public sealed class ResourceD : RESTResource
{
[RESTRoute(Method = HttpMethod.GET, PathInfo = @"^/resource/d")]
public void MyGetResponder(HttpListenerContext context)
{
this.SendTextResponse(context, "Resource D limited to http://localhost:1111");
}
}
[RESTScope(BaseUrl = "http://localhost:2222")]
public sealed class ResourceE : RESTResource
{
[RESTRoute(Method = HttpMethod.GET, PathInfo = @"^/resource/e$")]
public void MyGetResponder(HttpListenerContext context)
{
this.SendTextResponse(context, "Resource E limited to http://localhost:2222");
}
}
class Program
{
static void Main(string[] args)
{
var cluster = new RESTCluster();
cluster.Add("A", new RESTServer {Port= "1111"});
cluster.Add("B", new RESTServer {Port= "2222"});
cluster.StartAll();
Console.WriteLine("Press Enter to continue");
Console.ReadLine();
cluster.StopAll();
}
}
REST Client currently does not support authentication schemas by default. Authentication needs to be implemented by the consumer of the package.
expireDate = "last write time" + 23 hours. What you probably want is DateTime.Now + 23 hours. Expires is dependent on the system clock being correct and probably a bad choice, unless also combined with max-age and used maily for backward compatibility.
I would probably change it to "max-age": age + 86400 (1d), leaving the Last-Modified exactly as it is and removing Expires or changing it to be relative to DateTime.Now.
var lastWriteTime = File.GetLastWriteTimeUtc(path);
var lastModified = lastWriteTime.ToString("R");
var maxAge = (long)((DateTime.UtcNow - lastWriteTime).TotalSeconds + 86400);
It'd be nice to configure the value of EventLogger.LogExceptions from the Config object, which would allow you to turn it on and off using an external configuration file. It would make troubleshooting in production easier.
Allow opening of windows firewall when server starts and closing it when the server stops.
Add the ability to enable and disable routes. Only enabled routes should show up in the route list for a request, only enabled routes should be executed during routing.
RestClient.cs Line 63, the WebException instance won't necessarily have a Result that isn't null. When a timeout occurs this is generally null for instance. This results in an NRE when GetResponse() is called in RESTResponse's constructor.
Hello ,
I am using VS2012 and Grapevine 3.0.4 , when i use the Grapevine same machine with localhost
hostname , everything works well.
If I want to reach from other PC with client , Server could not be start listening with hostname ip address or Computername
If i try server pc set hostname to localhost , it starts listening but when reached from other PC with IP or name server returns bad request 400
Is it something wrong with my code or library.
My Server code is
public class embeddedHTTP //
{
private RESTServer Server;
public void ServerStart()
{
try
{
Server = new RESTServer();
Server.Port = GlobalVars.HttpHostPort;
Server.Host = GlobalVars.HttpHostAdress; // THIS ONLY WORKS FOR LOCALHOST
Server.MaxThreads = 20;
Server.Start();
while (Server.IsListening)
{
Thread.Sleep(GlobalVars.HttpHostRespTime);
}
}
catch (Exception ex)
{
messenger.logque("embedded HTTP server not started, Error ID : 52", 3, null);
}
}
public void ServerStop()
{
Server.Stop();
}
public sealed class MyResource : RESTResource
{
//d+$^ [a-zA-Z]+
[RESTRoute(Method = Grapevine.HttpMethod.GET, PathInfo = @"/")]
public void HandleFooRequests(HttpListenerContext context)
{
// String RawuR = context.Request.RawUrl;
String URL = Convert.ToString(context.Request.Url);
String ResultXML = brain.HTTPCMD(URL);
this.SendTextResponse(context, ResultXML);
}
}
}
While implementing some tests in an application where a RESTServer is started this exception occurred at the end of the test:
An exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll and wasn't
handled before a managed/native boundaryAdditional information Der Thread wurde abgebrochen.
This stack trace of external code was visible:
mscorlib.dll!System.Threading.WaitHandle.WaitAny(System.Threading.WaitHandle[] waitHandles, int millisecondsTimeout, bool exitContext) Unknown
mscorlib.dll!System.Threading.WaitHandle.WaitAny(System.Threading.WaitHandle[] waitHandles) Unknown
Grapevine.dll!Grapevine.Server.RESTServer.Worker() Unknown
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) Unknown
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Unknown
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Unknown
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Unknown
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() Unknown
The tests are green so it is only noticeable when the debugger is attached. It is just an exception occurring when the test runner is tearing down the test environment.
I am reporting this because this even happens when I stop the the RESTServer in the test code. I don't understand why the exception still occurs at the end. Maybe the ThreadAbortException
can be catched?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.