/// <summary>Process the request.</summary>
        /// <param name="context">The context.</param>
        /// <returns>An asynchronous result that yields a HttpResponseMessage.</returns>
        internal static async Task <HttpResponseMessage> Process(HttpContext context)
        {
            string fhirServerUrl = ProcessorUtils.GetFhirServerUrlR4(context.Request);

            if (context.Request.Path.Value.Length > 4)
            {
                context.Request.Path = new PathString(context.Request.Path.Value.Substring(3));
            }

            // proxy this call
            ForwardContext proxiedContext = context.ForwardTo(fhirServerUrl);

            // send to server and await response
            HttpResponseMessage response = await proxiedContext.Send().ConfigureAwait(false);

            // get copies of data when we care
            switch (context.Request.Method.ToUpperInvariant())
            {
            case "GET":
                ProcessGet(ref context, ref response);

                break;

            default:

                // ignore
                break;
            }

            // return the originator response, plus any modifications we've done
            return(response);
        }
Example #2
0
        /// <summary>Process the given context.</summary>
        /// <param name="context">The context.</param>
        /// <returns>An asynchronous result that yields a HttpResponseMessage.</returns>
        internal static async Task <HttpResponseMessage> Process(HttpContext context)
        {
            // create our response object
            HttpResponseMessage response = new HttpResponseMessage();

            if (ProcessorUtils.IsOperation(context.Request, out string operationName, out string prevComponent))
            {
                response.StatusCode = System.Net.HttpStatusCode.NotImplemented;
                return(response);
            }

            // get copies of data when we care
            switch (context.Request.Method.ToUpperInvariant())
            {
            case "GET":
                ProcessGet(ref context, ref response);

                break;

            default:
                // tell client we didn't understand
                response.StatusCode = System.Net.HttpStatusCode.NotImplemented;

                break;
            }

            // return the originator response, plus any modifications we've done
            return(response);
        }
        /// <summary>Process an HTTP GET in FHIR R5</summary>
        /// <param name="context"> [in,out] The context.</param>
        /// <param name="response">[in,out] The response.</param>
        internal static void ProcessGet(ref HttpContext context, ref HttpResponseMessage response)
        {
            // check for an ID
            string requestUrl = context.Request.Path;

            if (requestUrl.EndsWith('/'))
            {
                requestUrl = requestUrl.Substring(0, requestUrl.Length - 1);
            }

            string id = requestUrl.Substring(requestUrl.LastIndexOf('/') + 1);

            if (id.ToLowerInvariant() == "subscription")
            {
                ProcessorUtils.SerializeR5(ref response, SubscriptionManagerR5.GetSubscriptionsBundle());
            }
            else if (SubscriptionManagerR5.TryGetSubscription(id, out Subscription foundSub))
            {
                ProcessorUtils.SerializeR5(ref response, foundSub);
            }
            else
            {
                response.StatusCode = HttpStatusCode.NotFound;
            }
        }
        /// <summary>Process the operation get ws binding token described by response.</summary>
        /// <param name="context">          [in,out] The context.</param>
        /// <param name="response">         [in,out] The response.</param>
        /// <param name="previousComponent">The previous component.</param>
        internal static void ProcessOperationGetWsBindingToken(
            ref HttpContext context,
            ref HttpResponseMessage response,
            string previousComponent)
        {
            List <string> ids = new List <string>();

            if (previousComponent != "Subscription")
            {
                ids.Add(previousComponent);
            }
            else
            {
                try
                {
                    using (TextReader reader = new StreamReader(context.Request.Body))
                    {
                        string requestContent = reader.ReadToEndAsync().Result;

                        Parameters opParams = _fhirParser.Parse <Parameters>(requestContent);

                        foreach (Parameters.ParameterComponent param in opParams.Parameter)
                        {
                            if (param.Name == "ids")
                            {
                                ids.Add((param.Value as Id).ToString());
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    response.StatusCode = HttpStatusCode.BadRequest;
                    response.Content    = new StringContent("Caught exception: " + ex.Message);
                    return;
                }
            }

            foreach (string id in ids)
            {
                if (!SubscriptionManagerR4.Exists(id))
                {
                    response.StatusCode = HttpStatusCode.BadRequest;
                    response.Content    = new StringContent($"Invalid subscription id: {id}");
                    return;
                }
            }

            SubscriptionWsBindingToken token = SubscriptionWsBindingToken.GetTokenR4(ids);

            WebsocketManager.RegisterToken(token);

            Parameters parameters = new Parameters();

            parameters.Add("token", new FhirString(token.Token.ToString()));
            parameters.Add("expiration", new FhirDateTime(new DateTimeOffset(token.ExpiresAt)));
            parameters.Add("subscriptions", new FhirString(string.Join(',', ids)));

            ProcessorUtils.SerializeR4(ref response, parameters);
        }
        /// <summary>Process the request.</summary>
        /// <param name="context">The context.</param>
        /// <returns>An asynchronous result that yields a HttpResponseMessage.</returns>
        internal static async Task <HttpResponseMessage> Process(HttpContext context)
        {
            string fhirServerUrl = ProcessorUtils.GetFhirServerUrlR4(context.Request);

            // determine if we need to ask the server for a current version of the resource
            switch (context.Request.Method)
            {
            case "PUT":
            case "POST":
            case "DELETE":

                // figure out if we need to ask the server about this
                break;

            default:
                // don't need to check for existing copy
                break;
            }

            if (context.Request.Path.Value.Length > 4)
            {
                context.Request.Path = new PathString(context.Request.Path.Value.Substring(3));
            }

            // proxy this call
            ForwardContext proxiedContext = context.ForwardTo(fhirServerUrl);

            // send to server and await response
            HttpResponseMessage response = await proxiedContext.Send().ConfigureAwait(false);

            //// get copies of data when we care
            //switch (context.Request.Method.ToUpperInvariant())
            //{
            //    case "PUT":
            //    case "POST":

            //        // grab the message body to look at
            //        string responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

            //        // run this Encounter through our Subscription Manager
            //        SubscriptionManager.ProcessEncounter(responseContent, response.Headers.Location);

            //        break;

            //    default:

            //        // just proxy
            //        break;
            //}

            // return the results of the proxied call
            return(response);
        }
        /// <summary>Process the operation topic list R4.</summary>
        /// <param name="response">[in,out] The response.</param>
        internal static void ProcessOperationTopicList(
            ref HttpResponseMessage response)
        {
            Parameters topics = new Parameters();

            foreach (string topicUrl in SubscriptionTopicManager.GetTopicUrlList())
            {
                topics.Add("subscription-topic-canonical", new Canonical(topicUrl));
            }

            ProcessorUtils.SerializeR4(ref response, topics);
        }
        /// <summary>Process the request.</summary>
        /// <param name="context">The context.</param>
        /// <returns>An asynchronous result that yields a HttpResponseMessage.</returns>
        internal static async Task <HttpResponseMessage> Process(HttpContext context)
        {
            // create our response objects
            HttpResponseMessage response = new HttpResponseMessage();

            if (ProcessorUtils.IsOperation(context.Request, out string operationName, out string prevComponent))
            {
                ProcessOperation(ref context, ref response, operationName, prevComponent);
                return(response);
            }

            // get copies of data when we care
            switch (context.Request.Method.ToUpperInvariant())
            {
            case "GET":
                ProcessGet(ref context, ref response);

                break;

            case "PUT":
                response.StatusCode = System.Net.HttpStatusCode.NotImplemented;

                break;

            case "POST":
                ProcessPost(ref context, ref response);

                break;

            case "DELETE":
                // ask the subscription manager to deal with this
                if (SubscriptionManagerR5.HandleDelete(context.Request))
                {
                    response.StatusCode = System.Net.HttpStatusCode.NoContent;
                }
                else
                {
                    response.StatusCode = System.Net.HttpStatusCode.InternalServerError;
                }

                break;

            default:
                // tell client we didn't understand
                response.StatusCode = System.Net.HttpStatusCode.NotImplemented;

                break;
            }

            // return the originator response, plus any modifications we've done
            return(response);
        }
        /// <summary>Process the operation status R5.</summary>
        /// <param name="context">          [in,out] The context.</param>
        /// <param name="response">         [in,out] The response.</param>
        /// <param name="previousComponent">The previous component.</param>
        internal static void ProcessOperationStatus(
            ref HttpContext context,
            ref HttpResponseMessage response,
            string previousComponent)
        {
            List <string> ids = new List <string>();

            if (previousComponent != "Subscription")
            {
                ids.Add(previousComponent);
            }
            else
            {
                foreach (KeyValuePair <string, StringValues> query in context.Request.Query)
                {
                    if (query.Key == "ids")
                    {
                        ids.AddRange(query.Value);
                    }
                }
            }

            // create a bundle for this message message
            Bundle bundle = new Bundle()
            {
                Type      = Bundle.BundleType.Searchset,
                Timestamp = new DateTimeOffset(DateTime.Now),
                Meta      = new Meta(),
                Entry     = new List <Bundle.EntryComponent>(),
            };

            foreach (string id in ids)
            {
                if (SubscriptionManagerR5.TryGetSubscriptionStatus(id, out SubscriptionStatus status, 0, true))
                {
                    bundle.Entry.Add(new Bundle.EntryComponent()
                    {
                        FullUrl  = Program.UrlForR5ResourceId(status.TypeName, status.Id),
                        Resource = status,
                        Search   = new Bundle.SearchComponent()
                        {
                            Mode = Bundle.SearchEntryMode.Match,
                        },
                    });
                }
            }

            ProcessorUtils.SerializeR5(ref response, bundle);
        }
Example #9
0
        /// <summary>Process the request.</summary>
        /// <param name="context">The context.</param>
        /// <returns>An asynchronous result that yields a HttpResponseMessage.</returns>
        internal static async Task <HttpResponseMessage> Process(HttpContext context)
        {
            string fhirServerUrl = ProcessorUtils.GetFhirServerUrlR4(context.Request);

            if (context.Request.Path.Value.Length > 4)
            {
                context.Request.Path = new PathString(context.Request.Path.Value.Substring(3));
            }

            // context.Request.Headers["Accept-Encoding"] = "";
            // proxy this call
            ForwardContext proxiedContext = context.ForwardTo(fhirServerUrl);

            // send to server and await response
            HttpResponseMessage response = await proxiedContext.Send().ConfigureAwait(false);

            // get copies of data when we care
            switch (context.Request.Method.ToUpperInvariant())
            {
            case "PUT":
            case "POST":

                // grab the message body to look at
                string responseContent = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

                if (response.IsSuccessStatusCode)
                {
                    // run this Encounter through our Subscription Manager
                    SubscriptionManagerR4.ProcessEncounter(
                        responseContent,
                        response.Headers.Location);
                }

                break;

            default:

                // ignore
                break;
            }

            // return the results of the proxied call
            return(response);
        }
        /// <summary>Process an R4 metadata GET.</summary>
        /// <param name="context"> [in,out] The context.</param>
        /// <param name="response">[in,out] The response.</param>
        private static void ProcessGet(
            ref HttpContext context,
            ref HttpResponseMessage response)
        {
            // check for a valid capability statement
            try
            {
                // grab the message body to look at
                string responseContent = response.Content.ReadAsStringAsync().Result;

                CapabilityStatement capabilities = _fhirParser.Parse <CapabilityStatement>(responseContent);

                if (capabilities.Software == null)
                {
                    capabilities.Software = new CapabilityStatement.SoftwareComponent()
                    {
                        Name    = $"Argo-Proxy: {Program.FhirServerUrlR5}",
                        Version = FileVersionInfo.GetVersionInfo(Assembly.GetEntryAssembly().Location).FileVersion.ToString(),
                    };
                }
                else
                {
                    capabilities.Software.Name    = $"Argo-Proxy: {capabilities.Software.Name}";
                    capabilities.Software.Version =
                        FileVersionInfo.GetVersionInfo(Assembly.GetEntryAssembly().Location).FileVersion.ToString()
                        + ": " + capabilities.Software.Version;
                }

                capabilities.Implementation = new CapabilityStatement.ImplementationComponent()
                {
                    Description = $"Argonaut Subscription Proxy to: {Program.FhirServerUrlR5}",
                    Url         = Program.PublicUrl,
                };

                // only support application/fhir+json
                capabilities.Format = new string[] { "application/fhir+json" };

                // make sure Subscription is present
                bool foundSubscription = false;
                bool foundWebSocketUrl = false;

                for (int restIndex = 0;
                     restIndex < capabilities.Rest.Count;
                     restIndex++)
                {
                    for (int resourceIndex = 0;
                         resourceIndex < capabilities.Rest[restIndex].Resource.Count;
                         resourceIndex++)
                    {
                        switch (capabilities.Rest[restIndex].Resource[resourceIndex].TypeName)
                        {
                        case "Subscription":
                            foundSubscription = true;
                            capabilities.Rest[restIndex].Resource[resourceIndex] = BuildSubscriptionResourceComponent();
                            break;
                        }
                    }

                    if (capabilities.Rest[restIndex].Extension != null)
                    {
                        for (int extIndex = 0;
                             extIndex < capabilities.Rest[restIndex].Extension.Count;
                             extIndex++)
                        {
                            if (capabilities.Rest[restIndex].Extension[extIndex].Url == ExtensionCapabilityWebsocket)
                            {
                                foundWebSocketUrl = true;
                                capabilities.Rest[restIndex].Extension[extIndex].Value = new Hl7.Fhir.Model.FhirUri(Program.WebsocketUrl);
                            }
                        }
                    }
                }

                if (!foundSubscription)
                {
                    capabilities.Rest[0].Resource.Add(BuildSubscriptionResourceComponent());
                }

                if (!foundWebSocketUrl)
                {
                    if (capabilities.Rest[0].Extension == null)
                    {
                        capabilities.Rest[0].Extension = new System.Collections.Generic.List <Hl7.Fhir.Model.Extension>();
                    }

                    capabilities.Rest[0].Extension.Add(new Hl7.Fhir.Model.Extension()
                    {
                        Url   = ExtensionCapabilityWebsocket,
                        Value = new Hl7.Fhir.Model.FhirUri(Program.WebsocketUrl),
                    });
                }

                // serialize
                ProcessorUtils.SerializeR4(ref response, capabilities);
            }
            catch (Exception ex)
            {
                // write to console
                Console.WriteLine($"Failed to parse capability statement, {ex.Message}");
            }
        }
Example #11
0
 /// <summary>Process the get.</summary>
 /// <param name="context"> [in,out] The context.</param>
 /// <param name="response">[in,out] The response message.</param>
 internal static void ProcessGet(ref HttpContext context, ref HttpResponseMessage response)
 {
     ProcessorUtils.SerializeR5(ref response, SubscriptionTopicManager.GetTopicsBundle());
 }