コード例 #1
0
            // Notify() sends a POST request to the Subscription's callback URL.
            // DispatchAsync could be used to keep this method from blocking if the server has many subscriptions
            public void Notify()
            {
                try
                {
                    HttpClientRequest req = new HttpClientRequest();
                    req.RequestType = RequestType.Post;

                    // First, resolve the hostname using the ResolveHost method
                    var    parsedUrl        = new UrlParser(SubscriberCallbackUrl);
                    string resolvedHostname = ResolveHost(parsedUrl.Hostname);

                    // Swap in the resolved hostname when setting the target URL of the notification
                    string resolvedUrl = parsedUrl.ToString().Replace(parsedUrl.Hostname, resolvedHostname);
                    req.Url = new UrlParser(resolvedUrl);
                    HttpHeaders headers = new HttpHeaders();
                    headers.SetHeaderValue("Notification-Type", NotificationType);
                    headers.SetHeaderValue("Link", "<" + ResourceUrl + ">, rel=\"Resource\"");
                    req.Header = headers;
                    req.FinalizeHeader();
                    HttpClientResponse res = notifier.Dispatch(req);

                    if (res.Code != 200)
                    {
                        CrestronConsole.PrintLine("Notification to " + resolvedUrl + " not acknowledged");
                    }

                    // Must call Dispose on the HttpClientResponse object to end the http session
                    res.Dispose();
                }
                catch (Exception e)
                {
                    CrestronConsole.PrintLine(e.ToString());
                }
            }
コード例 #2
0
        // Subscribe to a random relay port on the server control system. The RelayMonitor will print notifications
        // to the console when this relay changes state
        public void Subscribe(string serverHostname)
        {
            try
            {
                if (subscribed)
                {
                    CrestronConsole.PrintLine("The monitor can only subscribe to one relay at a time. Unsubscribe first");
                    return;
                }

                // point serverAPIUrl at the root of the remote CWS server
                serverAPIUrl = new UrlParser("http://" + serverHostname + "/cws/api/");

                // GET the relay collection and derive the number of relays
                // available on the control system from the response
                HttpClientRequest req           = new HttpClientRequest();
                UrlParser         collectionUrl = new UrlParser(serverAPIUrl, "relays"); // complete URL = baseUrl + relativeUrl

                req.Url         = collectionUrl;
                req.RequestType = RequestType.Get;
                HttpHeader acceptHeader = new HttpHeader("Accept", "application/vnd.collection+json");
                req.Header.AddHeader(acceptHeader);
                req.FinalizeHeader();
                HttpClientResponse res = client.Dispatch(req);

                if (res.Code == 200)
                {
                    CrestronConsole.PrintLine("Received GET response for the relay collection");

                    string  json       = res.ContentString;
                    JObject collection = JsonConvert.DeserializeObject <JObject>(json);
                    JArray  list       = (JArray)collection["collection"]["items"];
                    int     relayCount = list.Count;
                    Random  rnd        = new Random();
                    rlyID = rnd.Next(1, relayCount + 1);

                    CrestronConsole.PrintLine("Server control system has " + relayCount + " relays. Subscribing to relay #" + rlyID + "...");

                    // Subscribe the the web-hook for the Relay #rlyID
                    req = new HttpClientRequest();
                    UrlParser webhookUrl = new UrlParser(serverAPIUrl, "relays/" + rlyID + "/web-hooks");
                    req.Url         = webhookUrl;
                    req.RequestType = RequestType.Post;
                    // add the Content-Type and Notification-Type headers as required by the RESTful WebHooks standard
                    HttpHeaders headers = new HttpHeaders();
                    headers.SetHeaderValue("Content-Type", "text/uri-list"); // webhook expects POST body to contain a single URL
                    headers.SetHeaderValue("Notification-Type", "UPDATED");  // monitor wants to know when relay state is changed
                    req.Header = headers;
                    req.FinalizeHeader();
                    req.ContentString = listenUrl.ToString();
                    res = client.Dispatch(req);

                    if (res.Code == 201)                                               // successful POST, subscription resource has been created
                    {
                        subscriptionUrl = new UrlParser(res.Header["Location"].Value); // save the obscure URL to the new subscription resource
                        subscribed      = true;
                        CrestronConsole.PrintLine("Subscribed to Relay #" + rlyID);
                        CrestronConsole.PrintLine("Subscription resource URL: " + subscriptionUrl);
                    }
                    else
                    {
                        CrestronConsole.PrintLine("Failed to subscribe to " + rlyID);
                    }
                    // Must call Dispose on the HttpClientResponse object to end this HTTP session
                    res.Dispose();
                }
                else
                {
                    CrestronConsole.PrintLine("Failed to get relay collection");
                    return;
                }
            }
            catch (Exception e)
            {
                CrestronConsole.PrintLine("Error in Subscribe(): " + e.Message);
            }
            finally
            {
            }
        }
コード例 #3
0
            public void ProcessRequest(HttpCwsContext context)
            {
                try
                {
                    // Only respond to POST requests made to the listen URL's path
                    if (parent.listenUrl.Path == context.Request.Url.AbsolutePath)
                    {
                        if (context.Request.HttpMethod == "POST")
                        {
                            // GET the individual relay to observe its updated state
                            HttpClientRequest req        = new HttpClientRequest();
                            string            linkString = context.Request.Headers["Link"];

                            // The notification POST request contains a link to the updated resource in the Link header.
                            // in compliance with the RESTful WebHooks standard at
                            // https://webhooks.pbworks.com/w/page/13385128/RESTful%20WebHooks
                            // This URL will be nested between the '<' and '>' characters,
                            // as described in https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Link
                            int    startIndex    = linkString.IndexOf('<') + 1;
                            int    endIndex      = linkString.IndexOf('>');
                            string linkUrlString = linkString.Substring(startIndex, endIndex - startIndex);

                            UrlParser relayUrl = new UrlParser(linkUrlString);
                            req.Url         = relayUrl;
                            req.RequestType = RequestType.Get;
                            HttpHeader acceptHeader = new HttpHeader("Accept", "application/vnd.collection+json");
                            req.Header.AddHeader(acceptHeader);
                            req.FinalizeHeader();
                            HttpClientResponse res = parent.client.Dispatch(req);

                            int    rlyID;
                            string newState = "";
                            if (res.Code == 200)
                            {
                                JObject item = JsonConvert.DeserializeObject <JObject>(res.ContentString);

                                rlyID    = (int)item["collection"]["items"][0]["data"][0]["value"];
                                newState = (string)item["collection"]["items"][0]["data"][1]["value"];
                            }
                            else
                            {
                                CrestronConsole.PrintLine("Failed to get individual relay");
                                return;
                            }
                            // log the notification message to console
                            CrestronConsole.PrintLine("NOTIFICATION: Relay #" + rlyID + "'s state changed to " + newState);

                            // respond to notification with 200 OK
                            context.Response.StatusCode        = 200;
                            context.Response.StatusDescription = "OK";
                            context.Response.End();
                        }
                        else
                        {
                            context.Response.StatusCode        = 405;
                            context.Response.StatusDescription = "Method Not Allowed";
                            context.Response.End();
                        }
                    }
                    else // ignore all other URLs besides the listener URL
                    {
                        CrestronConsole.PrintLine("Sending back a 404");
                        context.Response.StatusCode        = 404;
                        context.Response.StatusDescription = "Not Found";
                        context.Response.End();
                    }
                }
                catch (Exception e)
                {
                    try
                    {
                        // Respond with error message
                        context.Response.StatusCode        = 500;
                        context.Response.StatusDescription = "Internal Server Error";
                        context.Response.End();
                        CrestronConsole.PrintLine("Error in ProcessRequest: " + e.Message);
                    }
                    catch (Exception ex)
                    {
                        CrestronConsole.PrintLine("ProcessRequest unable to send error response: " + ex.Message);
                    }
                }
                finally
                {
                    ErrorLog.Notice("Served response to " + context.Request.UserHostName);
                }
            }