/// <summary> /// Send a Bundle to a path on the server /// </summary> /// <param name="bundle">The contents of the Bundle to be sent</param> /// <param name="path">A path on the server to send the Bundle to</param> /// <returns>True if the bundle was successfully delivered, false otherwise</returns> /// <remarks>This method differs from Batch, in that it can be used to deliver a Bundle /// at the endpoint for messages, documents or binaries, instead of the batched update /// REST endpoint.</remarks> public Bundle DeliverToMailbox(Bundle bundle) { if (bundle == null) { throw Error.ArgumentNull("bundle"); } assertEndpoint(); var url = new RestUrl(_endpoint).AddPath("Mailbox"); if (bundle.GetBundleType() == BundleType.Document) { // Documents are merely "accepted" var req = prepareRequest("POST", url.Uri, bundle, null, expectBundleResponse: false); //return doRequest(req, HttpStatusCode.NoContent, () => (Bundle)null); return(doRequest(req, HttpStatusCode.OK, () => bundleFromResponse())); } else if (bundle.GetBundleType() == BundleType.Message) { // Messages, including Queries, expect a return message var req = prepareRequest("POST", url.Uri, bundle, null, expectBundleResponse: true); return(doRequest(req, HttpStatusCode.OK, () => bundleFromResponse())); } else { throw Error.Argument("bundle", "The bundle passed to the Mailbox endpoint needs to be a document or message (use SetBundleType to do so)"); } }
/// <summary> /// Implements comparison of two RestUrls based on the FHIR rules set out in http.html#2.1.0.1 /// </summary> /// <param name="other"></param> /// <returns></returns> public bool IsSameUrl(RestUrl other) { var meUri = new RestUrl(this).ClearParams().ToString().RemovePrefix("http://").RemovePrefix("https://"); var otherUri = new RestUrl(other).ClearParams().ToString().RemovePrefix("http://").RemovePrefix("https://"); return(meUri == otherUri); }
public IEnumerable <Tag> GetTags <TResource>(string id = null, string version = null) where TResource : Resource, new() { assertEndpoint(); if (version != null && id == null) { throw new ArgumentException("Must specify an id if you specify a version"); } RestUrl api; string collection = typeof(TResource).GetCollectionName(); if (id == null) { api = new RestUrl(_endpoint).CollectionTags(collection); } else { api = new RestUrl(_endpoint).ResourceTags(collection, id, version); } var req = prepareRequest("GET", api.Uri, null, null, expectBundleResponse: false); var result = doRequest(req, HttpStatusCode.OK, () => tagListFromResponse()); return(result.Category); }
public FhirResponse GetResponse(ResourceFormat? acceptFormat) { bool needsFormatParam = UseFormatParameter && acceptFormat.HasValue; var location = new RestUrl(_location); if(needsFormatParam) location.AddParam(HttpUtil.RESTPARAM_FORMAT, ContentType.BuildFormatParam(acceptFormat.Value)); var request = createRequest(location.ToString(), _method); if(acceptFormat != null && !UseFormatParameter) request.Accept = ContentType.BuildContentType(acceptFormat.Value, forBundle: false); if (_body != null) { request.WriteBody(_body); request.ContentType = _contentType; if(_contentLocation != null) request.Headers[HttpRequestHeader.ContentLocation] = _contentLocation; } if(_categoryHeader != null) request.Headers[HttpUtil.CATEGORY] = _categoryHeader; FhirResponse result = null; // Make sure the HttpResponse gets disposed! using (HttpWebResponse response = (HttpWebResponse)request.GetResponseNoEx()) { result = FhirResponse.FromHttpWebResponse(response); } return result; }
public void TestEscaping() { var url = new RestUrl("http://www.server.org/fhir"); url.AddParam("_since", FhirDateTime.Now().Value); var output = url.Uri; Assert.IsFalse(output.ToString().Contains("+")); // don't use un-escaped + }
public void TestBase() { var u = new RestUrl("http://www.hl7.org/svc"); Assert.IsTrue(u.IsEndpointFor("http://www.hl7.org/svc/Organization")); Assert.IsTrue(u.IsEndpointFor("http://www.hl7.org/svc/Organization/search?name=eve")); Assert.IsFalse(u.IsEndpointFor("http://www.hl7.org/svx/Organization")); }
public FhirResponse GetResponse(ResourceFormat?acceptFormat) { bool needsFormatParam = UseFormatParameter && acceptFormat.HasValue; var location = new RestUrl(_location); if (needsFormatParam) { location.AddParam(HttpUtil.RESTPARAM_FORMAT, ContentType.BuildFormatParam(acceptFormat.Value)); } System.Diagnostics.Debug.WriteLine("{0}: {1}", _method, location.Uri.OriginalString); var request = createRequest(location.Uri, _method); if (acceptFormat != null && !UseFormatParameter) { request.Accept = ContentType.BuildContentType(acceptFormat.Value, forBundle: false); } if (_body != null) { request.WriteBody(_body); request.ContentType = _contentType; if (_contentLocation != null) { request.Headers[HttpRequestHeader.ContentLocation] = _contentLocation; } } if (_categoryHeader != null) { request.Headers[HttpUtil.CATEGORY] = _categoryHeader; } FhirResponse result = null; #if !PORTABLE45 request.Timeout = Timeout; #endif // Make sure the HttpResponse gets disposed! if (_beforeRequest != null) { _beforeRequest(request); } using (HttpWebResponse response = (HttpWebResponse)request.GetResponseNoEx()) { result = FhirResponse.FromHttpWebResponse(response); if (_afterRequest != null) { _afterRequest(response); } } return(result); }
/// <summary> /// Get a conformance statement for the system /// </summary> /// <param name="useOptionsVerb">If true, uses the Http OPTIONS verb to get the conformance, otherwise uses the /metadata endpoint</param> /// <returns>A Conformance resource. Throws an exception if the operation failed.</returns> public ResourceEntry <Conformance> Conformance(bool useOptionsVerb = false) { assertEndpoint(); RestUrl url = useOptionsVerb ? new RestUrl(_endpoint) : new RestUrl(_endpoint).WithMetadata(); var req = prepareRequest(useOptionsVerb ? "OPTIONS" : "GET", url.Uri, null, null, expectBundleResponse: false); return(doRequest(req, HttpStatusCode.OK, () => resourceEntryFromResponse <Conformance>())); }
public IEnumerable <Tag> GetTags() { assertEndpoint(); var rl = new RestUrl(_endpoint).Tags(); var req = prepareRequest("GET", rl.Uri, null, null, expectBundleResponse: false); var result = doRequest(req, HttpStatusCode.OK, () => tagListFromResponse()); return(result.Category); }
public static RestUrl DeleteResourceTags(this RestUrl url, string collection, string id, string vid = null) { if (vid == null) { return(new RestUrl(url).AddPath(collection, id, RestOperation.TAGS, RestOperation.DELETE)); } else { return(new RestUrl(url).AddPath(collection, id, RestOperation.HISTORY, vid, RestOperation.TAGS, RestOperation.DELETE)); } }
public static RestUrl Validate(this RestUrl url, string collection, string id = null) { if (id != null) { return(new RestUrl(url).AddPath(collection, RestOperation.VALIDATE)); } else { return(new RestUrl(url).AddPath(collection, RestOperation.VALIDATE, id)); } }
public static RestUrl Search(this RestUrl url, string collection = null) { if (collection != null) { return(new RestUrl(url).AddPath(collection, RestOperation.SEARCH)); } else { return(new RestUrl(url).AddPath(RestOperation.SEARCH)); } }
public TransactionBuilder EndpointOperation(RestUrl endpoint, Parameters parameters, bool useGet = false) { var entry = newEntry(useGet ? Bundle.HTTPVerb.GET : Bundle.HTTPVerb.POST); entry.Resource = parameters; var path = new RestUrl(endpoint); addEntry(entry, path); return(this); }
/// <summary> /// Validates whether the contents of the resource would be acceptable as a create /// </summary> /// <typeparam name="TResource"></typeparam> /// <param name="resource">The entry containing the Resource data to use for the validation</param> /// <param name="result">Contains the OperationOutcome detailing why validation failed, or null if validation succeeded</param> /// <param name="tags">Optional list of tags to attach to the resource</param> /// <returns>True when validation was successful, false otherwise. Note that this function may still throw exceptions if non-validation related /// failures occur.</returns> public bool TryValidateCreate <TResource>(TResource resource, out OperationOutcome result, IEnumerable <Tag> tags = null) where TResource : Resource, new() { if (resource == null) { throw new ArgumentNullException("resource"); } var collection = typeof(Resource).GetCollectionName(); var url = new RestUrl(_endpoint).Validate(collection); result = doValidate(url, resource, tags); return(result == null || !result.Success()); }
public void Query() { RestUrl endpoint = new RestUrl("http://localhost/fhir"); RestUrl resturi; resturi = endpoint.Search("organization").AddParam("family", "Johnson").AddParam("given", "William"); Assert.AreEqual("http://localhost/fhir/organization/_search?family=Johnson&given=William", resturi.AsString); var rl2 = new RestUrl(resturi.Uri); rl2.AddParam("given","Piet"); Assert.AreEqual("http://localhost/fhir/organization/_search?family=Johnson&given=William&given=Piet", rl2.AsString); }
public async Task <WebResponse> GetResponseAsync(ResourceFormat?acceptFormat) { bool needsFormatParam = UseFormatParameter && acceptFormat.HasValue; var location = new RestUrl(_location); if (needsFormatParam) { location.AddParam(HttpUtil.RESTPARAM_FORMAT, ContentType.BuildFormatParam(acceptFormat.Value)); } System.Diagnostics.Debug.WriteLine("(async) {0}: {1}", _method, location.ToString()); HttpWebRequest request = createRequest(location.Uri, _method); if (acceptFormat != null && !UseFormatParameter) { request.Accept = ContentType.BuildContentType(acceptFormat.Value, forBundle: false); } if (_categoryHeader != null) { request.Headers[HttpUtil.CATEGORY] = _categoryHeader; } if (_body != null) { request.ContentType = _contentType; if (_contentLocation != null) { request.Headers[HttpRequestHeader.ContentLocation] = _contentLocation; } await request.WriteBodyAsync(_body); } // Make sure the caller disposes the HttpResponse gets disposed... if (_beforeRequest != null) { _beforeRequest(request); } var response = await request.GetResponseAsync(TimeSpan.FromMilliseconds(Timeout)); if (_afterRequest != null) { _afterRequest(response); } return(response); }
public void CreateFromEndPoint() { RestUrl endpoint = new RestUrl("http://localhost/fhir"); RestUrl resturi; resturi = endpoint.ForCollection("patient"); Assert.AreEqual("http://localhost/fhir/patient", resturi.AsString); resturi = endpoint.Resource("patient", "1"); Assert.AreEqual("http://localhost/fhir/patient/1", resturi.AsString); resturi = endpoint.Resource("patient", "1"); Assert.AreEqual("http://localhost/fhir/patient/1", resturi.AsString); }
public void TryNavigation() { var old = new RestUrl("http://www.hl7.org/svc/Organization/"); var rl = old.NavigateTo("../Patient/1/_history"); Assert.AreEqual("http://www.hl7.org/svc/Patient/1/_history", rl.ToString()); old = new RestUrl("http://hl7.org/fhir/Patient/1"); rl = old.NavigateTo("2"); Assert.AreEqual("http://hl7.org/fhir/Patient/2",rl.ToString()); rl = old.NavigateTo("../Observation/3"); Assert.AreEqual("http://hl7.org/fhir/Observation/3",rl.ToString()); }
public static Uri AddParam(this Uri uri, string name, params string[] values) { UriBuilder builder = new UriBuilder(uri); ICollection <Tuple <string, string> > paramlist = RestUrl.SplitParams(builder.Query).ToList(); foreach (string value in values) { paramlist.Add(new Tuple <string, string>(name, value)); } builder.Query = RestUrl.JoinParams(paramlist); return(builder.Uri); }
public TransactionBuilder Create(Resource body, SearchParams condition) { var entry = newEntry(Bundle.HTTPVerb.POST); entry.Resource = body; var path = newRestUrl().AddPath(body.TypeName); var nonExist = new RestUrl(path); nonExist.AddParams(condition.ToUriParamList()); entry.Request.IfNoneExist = nonExist.ToString(); addEntry(entry, path); return(this); }
public TransactionBuilder EndpointOperation(RestUrl endpoint, Parameters parameters, bool useGet = false) { var entry = newEntry(useGet ? Bundle.HTTPVerb.GET : Bundle.HTTPVerb.POST); // Brian: Not sure why we would create this parameters object as empty. // I would imagine that a null parameters object is different to an empty one? // if (parameters == null) // parameters = new Parameters(); entry.Resource = parameters; var path = new RestUrl(endpoint); addEntry(entry, path); return(this); }
private Bundle doSearch(string collection = null, SearchParam[] criteria = null, string sort = null, string[] includes = null, int?count = null) { assertEndpoint(); RestUrl url = null; if (collection != null) { // Since there is confusion between using /resource/?param, /resource?param, use // the /resource/search?param instead url = new RestUrl(_endpoint).Search(collection); } else { url = new RestUrl(_endpoint); } if (count.HasValue) { url.AddParam(HttpUtil.SEARCH_PARAM_COUNT, count.Value.ToString()); } if (sort != null) { url.AddParam(HttpUtil.SEARCH_PARAM_SORT, sort); } if (criteria != null) { foreach (var criterium in criteria) { url.AddParam(criterium.QueryKey, criterium.QueryValue); } } if (includes != null) { foreach (string includeParam in includes) { url.AddParam(HttpUtil.SEARCH_PARAM_INCLUDE, includeParam); } } return(FetchBundle(url.Uri)); }
public static RestUrl Search(this RestUrl url, Query q) { // The ResourceType is the only parameter that needs special handling, // since the others are all "normal" parameters. Just make sure we don't // include the special _type parameter on the REST url var result = url.Search(q.ResourceType); foreach (var par in q.Parameter) { var paramKey = Query.ExtractParamKey(par); if (paramKey != Query.SEARCH_PARAM_TYPE) { result.AddParam(Query.ExtractParamKey(par), Query.ExtractParamValue(par)); } } return(result); }
private void addHistoryEntry(RestUrl path, SummaryType?summaryOnly = null, int?pageSize = null, DateTimeOffset?since = null) { var entry = newEntry(Bundle.HTTPVerb.GET, InteractionType.History); if (summaryOnly.HasValue) { path.AddParam(SearchParams.SEARCH_PARAM_SUMMARY, summaryOnly.Value.ToString().ToLower()); } if (pageSize.HasValue) { path.AddParam(HttpUtil.HISTORY_PARAM_COUNT, pageSize.Value.ToString()); } if (since.HasValue) { path.AddParam(HttpUtil.HISTORY_PARAM_SINCE, PrimitiveTypeConverter.ConvertTo <string>(since.Value)); } addEntry(entry, path); }
public void DeleteTags <TResource>(IEnumerable <Tag> tags, string id, string version = null) where TResource : Resource, new() { if (id == null) { throw new ArgumentNullException("id"); } if (tags == null) { throw new ArgumentNullException("tags"); } assertEndpoint(); var collection = typeof(TResource).GetCollectionName(); var rl = new RestUrl(_endpoint).ResourceTags(collection, id, version); var req = prepareRequest("DELETE", rl.Uri, new TagList(tags), null, expectBundleResponse: false); doRequest(req, HttpStatusCode.NoContent, () => true); }
public static HttpWebRequest ToHttpRequest(this Bundle.BundleEntryComponent entry, Prefer bodyPreference, ResourceFormat format, bool useFormatParameter, out byte[] body) { System.Diagnostics.Debug.WriteLine("{0}: {1}", entry.Request.Method, entry.Request.Url); var interaction = entry.Request; body = null; if (entry.Resource != null && !(interaction.Method == Bundle.HTTPVerb.POST || interaction.Method == Bundle.HTTPVerb.PUT)) throw Error.InvalidOperation("Cannot have a body on an Http " + interaction.Method.ToString()); var location = new RestUrl(interaction.Url); if (useFormatParameter) location.AddParam(HttpUtil.RESTPARAM_FORMAT, Hl7.Fhir.Rest.ContentType.BuildFormatParam(format)); var request = (HttpWebRequest)HttpWebRequest.Create(location.Uri); request.Method = interaction.Method.ToString(); setAgent(request, ".NET FhirClient for FHIR " + Model.ModelInfo.Version); if (!useFormatParameter) request.Accept = Hl7.Fhir.Rest.ContentType.BuildContentType(format, forBundle: false); if (interaction.IfMatch != null) request.Headers["If-Match"] = interaction.IfMatch; if (interaction.IfNoneMatch != null) request.Headers["If-None-Match"] = interaction.IfNoneMatch; #if PORTABLE45 if (interaction.IfModifiedSince != null) request.Headers["If-Modified-Since"] = interaction.IfModifiedSince.Value.UtcDateTime.ToString(); #else if (interaction.IfModifiedSince != null) request.IfModifiedSince = interaction.IfModifiedSince.Value.UtcDateTime; #endif if (interaction.IfNoneExist != null) request.Headers["If-None-Exist"] = interaction.IfNoneExist; if (interaction.Method == Bundle.HTTPVerb.POST || interaction.Method == Bundle.HTTPVerb.PUT) { if (bodyPreference == Prefer.ReturnMinimal) request.Headers["Prefer"] = bodyPreference == Prefer.ReturnMinimal ? "return=minimal" : "return=representation"; } if (entry.Resource != null) setBodyAndContentType(request, entry.Resource, format, out body); return request; }
/// <summary> /// Retrieve the version history of any resource on the server /// </summary> /// <param name="since">Optional. Returns only changes after the given date</param> /// <param name="count">Optional. Asks server to limit the number of entries returned</param> /// <returns>A bundle with the history for the indicated instance, may contain both /// ResourceEntries and DeletedEntries.</returns> public Bundle WholeSystemHistory(DateTimeOffset?since = null, int?count = null) { if (_endpoint == null) { throw new InvalidOperationException("Endpoint must be provided using either the Endpoint property or the FhirClient constructor"); } var rl = new RestUrl(_endpoint).ServerHistory(); if (since != null) { rl.AddParam(HttpUtil.HISTORY_PARAM_SINCE, PrimitiveTypeConverter.ConvertTo <string>(since.Value)); } if (count != null) { rl.AddParam(HttpUtil.HISTORY_PARAM_COUNT, count.ToString()); } return(FetchBundle(rl.Uri)); }
public void DeliverToDocument(Bundle bundle) { if (bundle == null) { throw Error.ArgumentNull("bundle"); } assertEndpoint(); var url = new RestUrl(_endpoint).AddPath("Document"); if (bundle.GetBundleType() == BundleType.Document) { // Documents are merely "accepted" var req = prepareRequest("POST", url.Uri, bundle, null, expectBundleResponse: false); doRequest(req, HttpStatusCode.NoContent, () => true); } else { throw Error.Argument("bundle", "The bundle passed to the Document endpoint needs to be a document (use SetBundleType to do so)"); } }
private OperationOutcome doValidate(RestUrl url, object data, IEnumerable <Tag> tags) { var req = prepareRequest("POST", url.Uri, data, tags, expectBundleResponse: false); try { doRequest(req, HttpStatusCode.OK, () => true); return(null); } catch (FhirOperationException foe) { if (foe.Outcome != null) { return(foe.Outcome); } else { throw foe; } } }
/// <summary> /// Validates whether the contents of the resource would be acceptable as an update /// </summary> /// <param name="entry">The entry containing the updated Resource to validate</param> /// <param name="result">Contains the OperationOutcome detailing why validation failed, or null if validation succeeded</param> /// <returns>True when validation was successful, false otherwise. Note that this function may still throw exceptions if non-validation related /// failures occur.</returns> public bool TryValidateUpdate <TResource>(ResourceEntry <TResource> entry, out OperationOutcome result) where TResource : Resource, new() { if (entry == null) { throw new ArgumentNullException("entry"); } if (entry.Resource == null) { throw new ArgumentException("Entry does not contain a Resource to validate", "entry"); } if (entry.Id == null) { throw new ArgumentException("Entry needs a non-null entry.id to use for validation", "entry"); } var id = new ResourceIdentity(entry.Id); var url = new RestUrl(_endpoint).Validate(id.Collection, id.Id); result = doValidate(url, entry.Resource, entry.Tags); return(result == null || !result.Success()); }
public TransactionBuilder EndpointOperation(RestUrl endpoint, Parameters parameters, bool useGet = false) { var entry = newEntry(useGet ? Bundle.HTTPVerb.GET : Bundle.HTTPVerb.POST, InteractionType.Operation); var path = new RestUrl(endpoint); if (useGet) { if (parameters != null) { foreach (var parameter in parameters.Parameter) { path.AddParam(parameter.Name, paramValueToString(parameter)); } } } else { entry.Resource = parameters; } addEntry(entry, path); return(this); }
/// <summary> /// Create a resource /// </summary> /// <param name="collectionEndpoint">Endpoint where the resource is sent to be created</param> /// <param name="resource">The resource instance to create</param> /// <param name="tags">Optional. List of Tags to add to the created instance.</param> /// <returns>The resource as created on the server, or an exception if the create failed.</returns> /// <typeparam name="TResource">The type of resource to create</typeparam> /// <remarks><para>The returned resource need not be the same as the resources passed as a parameter, /// since the server may have updated or changed part of the data because of business rules.</para> /// </remarks> public ResourceEntry <TResource> Create <TResource>(TResource resource, string id = null, IEnumerable <Tag> tags = null) where TResource : Resource, new() { if (resource == null) { throw new ArgumentNullException("resource"); } assertEndpoint(); var collection = typeof(TResource).GetCollectionName(); if (id == null) { // A normal create var rl = new RestUrl(_endpoint).ForCollection(collection); var req = prepareRequest("POST", rl.Uri, resource, tags, expectBundleResponse: false); return(doRequest(req, HttpStatusCode.Created, () => makeEntryFromHeaders(resource))); } else { // Given an id, this create turns into an update at a specific resource location return(Update <TResource>(resource, id, tags)); } }
public void ParamManipulation() { var rl = new RestUrl("http://someserver.org/fhir/Patient/search?name=Kramer&name=Moreau&oauth=XXX"); rl.AddParam("newParamA", "1"); rl.SetParam("newParamB", "2"); Assert.IsTrue(rl.ToString().EndsWith("oauth=XXX&newParamA=1&newParamB=2")); rl.SetParam("newParamA", "3"); rl.ClearParam("newParamB"); Assert.IsTrue(rl.ToString().EndsWith("oauth=XXX&newParamA=3")); rl.AddParam("newParamA", "4"); Assert.IsTrue(rl.ToString().EndsWith("oauth=XXX&newParamA=3&newParamA=4")); rl.AddParam("newParamB", "5"); Assert.IsTrue(rl.ToString().EndsWith("oauth=XXX&newParamA=3&newParamA=4&newParamB=5")); rl.SetParam("newParamA", "6"); Assert.IsTrue(rl.ToString().EndsWith("oauth=XXX&newParamA=6&newParamB=5")); rl.ClearParams(); Assert.IsTrue(rl.ToString().EndsWith("search")); }
public void AreSame() { var rl = new RestUrl("http://someserver.org/Patient/4?oauth=xxxx"); var rl2 = new RestUrl("https://someserver.org/Patient/4"); Assert.IsTrue(rl.IsSameUrl(rl2)); Assert.IsTrue(rl2.IsSameUrl(rl)); rl2 = new RestUrl("http://someserver.org/Patient/4"); Assert.IsTrue(rl.IsSameUrl(rl2)); Assert.IsTrue(rl2.IsSameUrl(rl)); rl2 = new RestUrl("https://someserver.org:81/Patient/4"); Assert.IsFalse(rl.IsSameUrl(rl2)); Assert.IsFalse(rl2.IsSameUrl(rl)); }
public Bundle History(string collection, string id, DateTimeOffset? since) { RequestValidator.ValidateCollectionName(collection); RequestValidator.ValidateId(id); if (since == null) since = DateTimeOffset.MinValue; string title = String.Format("History for updates on '{0}' resource '{1}' since {2}", collection, id, since); RestUrl self = new RestUrl(this.Endpoint).AddPath(collection, id, RestOperation.HISTORY); if (!entryExists(collection, id)) throw new SparkException(HttpStatusCode.NotFound, "There is no history because there is no {0} resource with id {1}.", collection, id); var identity = ResourceIdentity.Build(collection, id).OperationPath; IEnumerable<BundleEntry> entries = store.ListVersionsById(identity, since, Const.MAX_HISTORY_RESULT_SIZE); //Bundle bundle = BundleEntryFactory.CreateBundleWithEntries(title, self.Uri, Const.AUTHOR, Settings.AuthorUri, entries); var snapshot = Snapshot.Create(title, self.Uri, null, entries, Snapshot.NOCOUNT); return exportPagedSnapshot(snapshot); }
public static HttpWebRequest ToHttpWebRequest(this EntryRequest entry, Uri baseUrl, FhirClientSettings settings) { System.Diagnostics.Debug.WriteLine("{0}: {1}", (object)entry.Method, (object)entry.Url); if (entry.RequestBodyContent != null && !(entry.Method == HTTPVerb.POST || entry.Method == HTTPVerb.PUT)) { throw Error.InvalidOperation((string)("Cannot have a body on an Http " + entry.Method.ToString())); } // Create an absolute uri when the interaction.Url is relative. var uri = new Uri(entry.Url, UriKind.RelativeOrAbsolute); if (!uri.IsAbsoluteUri) { uri = HttpUtil.MakeAbsoluteToBase(uri, baseUrl); } var location = new RestUrl(uri); if (settings.UseFormatParameter) { location.AddParam(HttpUtil.RESTPARAM_FORMAT, ContentType.BuildFormatParam(settings.PreferredFormat)); } var request = (HttpWebRequest)HttpWebRequest.Create(location.Uri); request.Method = entry.Method.ToString(); setAgent(request, ".NET FhirClient for FHIR " + entry.Agent); if (!settings.UseFormatParameter) { request.Accept = ContentType.BuildContentType(settings.PreferredFormat, forBundle: false); } request.ContentType = entry.ContentType ?? ContentType.BuildContentType(settings.PreferredFormat, forBundle: false); if (entry.Headers.IfMatch != null) { request.Headers["If-Match"] = entry.Headers.IfMatch; } if (entry.Headers.IfNoneMatch != null) { request.Headers["If-None-Match"] = entry.Headers.IfNoneMatch; } #if NETSTANDARD1_1 if (entry.Headers.IfModifiedSince != null) { request.Headers["If-Modified-Since"] = entry.Headers.IfModifiedSince.Value.UtcDateTime.ToString(); } #else if (entry.Headers.IfModifiedSince != null) { request.IfModifiedSince = entry.Headers.IfModifiedSince.Value.UtcDateTime; } #endif if (entry.Headers.IfNoneExist != null) { request.Headers["If-None-Exist"] = entry.Headers.IfNoneExist; } if (canHaveReturnPreference() && settings.PreferredReturn.HasValue) { if (settings.PreferredReturn == Prefer.RespondAsync) { request.Headers["Prefer"] = PrimitiveTypeConverter.ConvertTo <string>(settings.PreferredReturn); } else { request.Headers["Prefer"] = "return=" + PrimitiveTypeConverter.ConvertTo <string>(settings.PreferredReturn); } } else if (entry.Type == InteractionType.Search) { List <string> preferHeader = new List <string>(); if (settings.PreferredParameterHandling.HasValue) { preferHeader.Add("handling=" + settings.PreferredParameterHandling.GetLiteral()); } if (settings.PreferredReturn.HasValue && settings.PreferredReturn == Prefer.RespondAsync) { preferHeader.Add(settings.PreferredReturn.GetLiteral()); } if (preferHeader.Count > 0) { request.Headers["Prefer"] = string.Join(", ", preferHeader); } } bool canHaveReturnPreference() => entry.Type == InteractionType.Create || entry.Type == InteractionType.Update || entry.Type == InteractionType.Patch; // PCL doesn't support setting the length (and in this case will be empty anyway) #if !NETSTANDARD1_1 if (entry.RequestBodyContent == null) { request.ContentLength = 0; } #endif return(request); }
private void addEntry(Bundle.BundleEntryComponent newEntry, RestUrl path) { newEntry.Transaction.Url = path.Uri.ToString(); _result.Entry.Add(newEntry); }
public RestUrl(RestUrl url) : this(url.Uri) { }
public FhirResponse GetResponse(ResourceFormat? acceptFormat) { bool needsFormatParam = UseFormatParameter && acceptFormat.HasValue; var location = new RestUrl(_location); if(needsFormatParam) location.AddParam(HttpUtil.RESTPARAM_FORMAT, ContentType.BuildFormatParam(acceptFormat.Value)); System.Diagnostics.Debug.WriteLine("{0}: {1}", _method, location.Uri.OriginalString); var request = createRequest(location.Uri, _method); if(acceptFormat != null && !UseFormatParameter) request.Accept = ContentType.BuildContentType(acceptFormat.Value, forBundle: false); if (_body != null) { request.WriteBody(_body); request.ContentType = _contentType; if(_contentLocation != null) request.Headers[HttpRequestHeader.ContentLocation] = _contentLocation; } if(_categoryHeader != null) request.Headers[HttpUtil.CATEGORY] = _categoryHeader; FhirResponse fhirResponse = null; #if !PORTABLE45 request.Timeout = Timeout; #endif // Make sure the HttpResponse gets disposed! if (_beforeRequest != null) _beforeRequest(request, _body); using (HttpWebResponse webResponse = (HttpWebResponse)request.GetResponseNoEx()) { fhirResponse = FhirResponse.FromHttpWebResponse(webResponse); if (_afterRequest != null) _afterRequest(webResponse, fhirResponse); } return fhirResponse; }
private void addHistoryEntry(RestUrl path, bool? summaryOnly = null, int? pageSize=null, DateTimeOffset? since = null) { var entry = newEntry(Bundle.HTTPVerb.GET); if(summaryOnly.HasValue) path.AddParam(SearchParams.SEARCH_PARAM_SUMMARY, PrimitiveTypeConverter.ConvertTo<string>(summaryOnly.Value)); if(pageSize.HasValue) path.AddParam(HttpUtil.HISTORY_PARAM_COUNT, pageSize.Value.ToString()); if(since.HasValue) path.AddParam(HttpUtil.HISTORY_PARAM_SINCE, PrimitiveTypeConverter.ConvertTo<string>(since.Value)); addEntry(entry, path); }
private void addEntry(Bundle.EntryComponent newEntry, RestUrl path) { newEntry.Request.Url = path.Uri.ToString(); _result.Entry.Add(newEntry); }
private Uri tryCreatePatient(FhirClient client, ResourceFormat formatIn, string id = null) { client.PreferredFormat = formatIn; ResourceEntry<Patient> created = null; Patient demopat = DemoData.GetDemoPatient(); if (id == null) { HttpTests.AssertSuccess(client, () => created = client.Create<Patient>(demopat)); } else { HttpTests.AssertSuccess(client, () => created = client.Create<Patient>(demopat, id)); var ep = new RestUrl(client.Endpoint); if (!ep.IsEndpointFor(created.Id)) TestResult.Fail("Location of created resource is not located within server endpoint"); var rl = new ResourceIdentity(created.Id); if (rl.Id != id) TestResult.Fail("Server refused to honor client-assigned id"); } HttpTests.AssertLocationPresentAndValid(client); // Create bevat geen response content meer. Terecht verwijderd?: // EK: Niet helemaal, er is weliswaar geen data meer gereturned, maar de headers (id, versie, modified) worden // nog wel geupdate HttpTests.AssertContentLocationValidIfPresent(client); return created.SelfLink; }
public FhirResponse Search(string type, SearchParams searchCommand) { Validate.TypeName(type); SearchResults results = index.Search(type, searchCommand); if (results.HasErrors) { throw new SparkException(HttpStatusCode.BadRequest, results.Outcome); } Uri link = new RestUrl(localhost.Uri(type)).AddPath(results.UsedParameters).Uri; string firstSort = null; if (searchCommand.Sort != null && searchCommand.Sort.Count() > 0) { firstSort = searchCommand.Sort[0].Item1; //TODO: Support sortorder and multiple sort arguments. } var snapshot = pager.CreateSnapshot(Bundle.BundleType.Searchset, link, results, firstSort); Bundle bundle = pager.GetFirstPage(snapshot); return Respond.WithBundle(bundle, localhost.Base); }
public Bundle Search(string collection, IEnumerable<Tuple<string, string>> parameters, int pageSize) { RequestValidator.ValidateCollectionName(collection); string title = String.Format("Search on resources in collection '{0}'", collection); Query query = FhirParser.ParseQueryFromUriParameters(collection, parameters); ICollection<string> includes = query.Includes; SearchResults results = _index.Search(query); if (results.HasErrors) { throw new SparkException(HttpStatusCode.BadRequest, results.Outcome); } RestUrl selfLink = new RestUrl(Endpoint).AddPath(collection).AddPath(results.UsedParameters); Snapshot snapshot = Snapshot.Create(title, selfLink.Uri, includes, results, results.MatchCount); Bundle bundle = pager.FirstPage(snapshot, pageSize); //TODO: This replaces the selflink with a link to the snapshot... store.Include(bundle, includes); if (results.HasIssues) { var outcomeEntry = BundleEntryFactory.CreateFromResource(results.Outcome, new Uri("outcome/1", UriKind.Relative), DateTimeOffset.Now); outcomeEntry.SelfLink = outcomeEntry.Id; bundle.Entries.Add(outcomeEntry); } exporter.EnsureAbsoluteUris(bundle); return bundle; }
public Bundle History(DateTimeOffset? since) { if (since == null) since = DateTimeOffset.MinValue; string title = String.Format("Full server-wide history for updates since {0}", since); RestUrl self = new RestUrl(this.Endpoint).AddPath(RestOperation.HISTORY); /*IEnumerable<BundleEntry> entries = store.ListVersions(since, Const.MAX_HISTORY_RESULT_SIZE); Snapshot snapshot = Snapshot.Create(title, self.Uri, null, entries, entries.Count()); */ ICollection<Uri> keys = store.HistoryKeys(since); Snapshot snapshot = Snapshot.Create(title, self.Uri, null, keys, keys.Count()); Bundle bundle = pager.FirstPage(snapshot, Const.DEFAULT_PAGE_SIZE); exporter.EnsureAbsoluteUris(bundle); return bundle; }
public TransactionBuilder EndpointOperation(RestUrl endpoint, Parameters parameters, bool useGet = false) { var entry = newEntry(useGet ? Bundle.HTTPVerb.GET : Bundle.HTTPVerb.POST); entry.Resource = parameters; var path = new RestUrl(endpoint); addEntry(entry, path); return this; }
public TransactionBuilder EndpointOperation(RestUrl endpoint, string name, Parameters parameters, bool useGet = false) { var path = new RestUrl(endpoint).AddPath(OPERATIONPREFIX + name); return(EndpointOperation(path, parameters, useGet)); }
public TransactionBuilder Create(Resource body, SearchParams condition) { var entry = newEntry(Bundle.HTTPVerb.POST); entry.Resource = body; var path = newRestUrl().AddPath(body.TypeName); var nonExist = new RestUrl(path); nonExist.AddParams(condition.ToUriParamList()); entry.Request.IfNoneExist = nonExist.ToString(); addEntry(entry, path); return this; }
private void addEntry(Bundle.EntryComponent newEntry, RestUrl path) { newEntry.Request.Url = HttpUtil.MakeRelativeFromBase(path.Uri, _baseUrl).ToString(); _result.Entry.Add(newEntry); }
public Bundle History(string collection, string id, DateTimeOffset? since, string sortby) { Uri key = BuildKey(collection, id); if (!store.Exists(key)) throw new SparkException(HttpStatusCode.NotFound, "There is no history because there is no {0} resource with id {1}.", collection, id); string title = String.Format("History for updates on '{0}' resource '{1}' since {2}", collection, id, since); RestUrl self = new RestUrl(this.Endpoint).AddPath(collection, id, RestOperation.HISTORY); IEnumerable<Uri> keys = store.History(key, since); Bundle bundle = pager.CreateSnapshotAndGetFirstPage(title, self.Uri, keys, sortby); exporter.Externalize(bundle); return bundle; }
public static HttpWebRequest ToHttpRequest(this Bundle.EntryComponent entry, Prefer bodyPreference, ResourceFormat format, bool useFormatParameter, bool CompressRequestBody, out byte[] body) { System.Diagnostics.Debug.WriteLine("{0}: {1}", entry.Request.Method, entry.Request.Url); var interaction = entry.Request; body = null; if (entry.Resource != null && !(interaction.Method == Bundle.HTTPVerb.POST || interaction.Method == Bundle.HTTPVerb.PUT)) { throw Error.InvalidOperation("Cannot have a body on an Http " + interaction.Method.ToString()); } var location = new RestUrl(interaction.Url); if (useFormatParameter) { location.AddParam(HttpUtil.RESTPARAM_FORMAT, Hl7.Fhir.Rest.ContentType.BuildFormatParam(format)); } var request = (HttpWebRequest)HttpWebRequest.Create(location.Uri); request.Method = interaction.Method.ToString(); setAgent(request, ".NET FhirClient for FHIR " + Model.ModelInfo.Version); if (!useFormatParameter) { request.Accept = Hl7.Fhir.Rest.ContentType.BuildContentType(format, forBundle: false); } if (interaction.IfMatch != null) { request.Headers["If-Match"] = interaction.IfMatch; } if (interaction.IfNoneMatch != null) { request.Headers["If-None-Match"] = interaction.IfNoneMatch; } #if DOTNETFW if (interaction.IfModifiedSince != null) { request.IfModifiedSince = interaction.IfModifiedSince.Value.UtcDateTime; } #else if (interaction.IfModifiedSince != null) { request.Headers["If-Modified-Since"] = interaction.IfModifiedSince.Value.UtcDateTime.ToString(); } #endif if (interaction.IfNoneExist != null) { request.Headers["If-None-Exist"] = interaction.IfNoneExist; } if (interaction.Method == Bundle.HTTPVerb.POST || interaction.Method == Bundle.HTTPVerb.PUT) { request.Headers["Prefer"] = bodyPreference == Prefer.ReturnMinimal ? "return=minimal" : "return=representation"; } if (entry.Resource != null) { setBodyAndContentType(request, entry.Resource, format, CompressRequestBody, out body); } // PCL doesn't support setting the length (and in this case will be empty anyway) #if DOTNETFW else { request.ContentLength = 0; } #endif return(request); }
/// <summary> /// Implements comparison of two RestUrls based on the FHIR rules set out in http.html#2.1.0.1 /// </summary> /// <param name="other"></param> /// <returns></returns> public bool IsSameUrl(RestUrl other) { var meUri = new RestUrl(this).ClearParams().ToString().RemovePrefix("http://").RemovePrefix("https://"); var otherUri = new RestUrl(other).ClearParams().ToString().RemovePrefix("http://").RemovePrefix("https://"); return meUri == otherUri; }
public async Task<WebResponse> GetResponseAsync(ResourceFormat? acceptFormat) { bool needsFormatParam = UseFormatParameter && acceptFormat.HasValue; var location = new RestUrl(_location); if (needsFormatParam) location.AddParam(HttpUtil.RESTPARAM_FORMAT, ContentType.BuildFormatParam(acceptFormat.Value)); System.Diagnostics.Debug.WriteLine("(async) {0}: {1}", _method, location.ToString()); HttpWebRequest request = createRequest(location.Uri, _method); if (acceptFormat != null && !UseFormatParameter) request.Accept = ContentType.BuildContentType(acceptFormat.Value, forBundle: false); if (_categoryHeader != null) request.Headers[HttpUtil.CATEGORY] = _categoryHeader; if (_body != null) { request.ContentType = _contentType; if (_contentLocation != null) request.Headers[HttpRequestHeader.ContentLocation] = _contentLocation; await request.WriteBodyAsync(_body); } // Make sure the caller disposes the HttpResponse gets disposed... if (_beforeRequest != null) _beforeRequest(request); var webResponse = await request.GetResponseAsync(TimeSpan.FromMilliseconds(Timeout)); if (_afterRequest != null) _afterRequest(webResponse, null); return response; }
public Bundle History(string collection, DateTimeOffset? since, string sortby) { RequestValidator.ValidateCollectionName(collection); string title = String.Format("Full server-wide history for updates since {0}", since); RestUrl self = new RestUrl(this.Endpoint).AddPath(collection, RestOperation.HISTORY); IEnumerable<Uri> keys = store.History(collection, since); Snapshot snapshot = Snapshot.Create(title, self.Uri, keys, sortby); store.AddSnapshot(snapshot); Bundle bundle = pager.GetPage(snapshot); exporter.Externalize(bundle); return bundle; }
public static HttpRequestMessage ToHttpRequestMessage(this EntryRequest entry, Uri baseUrl, FhirClientSettings settings) { System.Diagnostics.Debug.WriteLine("{0}: {1}", entry.Method, entry.Url); if (entry.RequestBodyContent != null && !(entry.Method == HTTPVerb.POST || entry.Method == HTTPVerb.PUT)) { throw Error.InvalidOperation("Cannot have a body on an Http " + entry.Method.ToString()); } // Create an absolute uri when the interaction.Url is relative. var uri = new Uri(entry.Url, UriKind.RelativeOrAbsolute); if (!uri.IsAbsoluteUri) { uri = HttpUtil.MakeAbsoluteToBase(uri, baseUrl); } var location = new RestUrl(uri); if (settings.UseFormatParameter) { location.AddParam(HttpUtil.RESTPARAM_FORMAT, ContentType.BuildFormatParam(settings.PreferredFormat)); } var request = new HttpRequestMessage(getMethod(entry.Method), location.Uri); request.Headers.Add("User-Agent", ".NET FhirClient for FHIR " + entry.Agent); if (!settings.UseFormatParameter) { request.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse(ContentType.BuildContentType(settings.PreferredFormat, forBundle: false))); } if (entry.Headers.IfMatch != null) { request.Headers.Add("If-Match", entry.Headers.IfMatch); } if (entry.Headers.IfNoneMatch != null) { request.Headers.Add("If-None-Match", entry.Headers.IfNoneMatch); } if (entry.Headers.IfModifiedSince != null) { request.Headers.IfModifiedSince = entry.Headers.IfModifiedSince.Value.UtcDateTime; } if (entry.Headers.IfNoneExist != null) { request.Headers.Add("If-None-Exist", entry.Headers.IfNoneExist); } var interactionType = entry.Type; bool canHaveReturnPreference() => entry.Type == InteractionType.Create || entry.Type == InteractionType.Update || entry.Type == InteractionType.Patch; if (canHaveReturnPreference() && settings.PreferredReturn != null) { if (settings.PreferredReturn == Prefer.RespondAsync) { request.Headers.Add("Prefer", PrimitiveTypeConverter.ConvertTo <string>(settings.PreferredReturn)); } else { request.Headers.Add("Prefer", "return=" + PrimitiveTypeConverter.ConvertTo <string>(settings.PreferredReturn)); } } else if (interactionType == InteractionType.Search && settings.PreferredParameterHandling != null) { List <string> preferHeader = new List <string>(); if (settings.PreferredParameterHandling.HasValue) { preferHeader.Add("handling=" + settings.PreferredParameterHandling.GetLiteral()); } if (settings.PreferredReturn.HasValue && settings.PreferredReturn == Prefer.RespondAsync) { preferHeader.Add(settings.PreferredReturn.GetLiteral()); } if (preferHeader.Count > 0) { request.Headers.Add("Prefer", string.Join(", ", preferHeader)); } } if (entry.RequestBodyContent != null) { setContentAndContentType(request, entry.RequestBodyContent, entry.ContentType, settings.PreferredFormat); } return(request); }
public Bundle History(DateTimeOffset? since, string sortby) { if (since == null) since = DateTimeOffset.MinValue; string title = String.Format("Full server-wide history for updates since {0}", since); RestUrl self = new RestUrl(this.Endpoint).AddPath(RestOperation.HISTORY); IEnumerable<Uri> keys = store.History(since); Snapshot snapshot = Snapshot.Create(title, self.Uri, keys, sortby); store.AddSnapshot(snapshot); Bundle bundle = pager.GetPage(snapshot, 0, Const.DEFAULT_PAGE_SIZE); exporter.Externalize(bundle); return bundle; }
public TransactionBuilder EndpointOperation(RestUrl endpoint, string name, Parameters parameters, bool useGet = false) { var path = new RestUrl(endpoint).AddPath(OPERATIONPREFIX + name); return EndpointOperation(path, parameters, useGet); }
public Bundle History(string collection, DateTimeOffset? since) { RequestValidator.ValidateCollectionName(collection); if (since == null) since = DateTimeOffset.MinValue; string title = String.Format("Full server-wide history for updates since {0}", since); RestUrl self = new RestUrl(this.Endpoint).AddPath(collection, RestOperation.HISTORY); IEnumerable<BundleEntry> entries = store.ListVersionsInCollection(collection, since, Const.MAX_HISTORY_RESULT_SIZE); // Bundle bundle = BundleEntryFactory.CreateBundleWithEntries(title, self.Uri, Const.AUTHOR, Settings.AuthorUri, entries); var snapshot = Snapshot.Create(title, self.Uri, null, entries, Snapshot.NOCOUNT); return exportPagedSnapshot(snapshot); }