-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Expand file tree
/
Copy pathApiHandlers.cs
More file actions
118 lines (106 loc) · 5.13 KB
/
ApiHandlers.cs
File metadata and controls
118 lines (106 loc) · 5.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
using System;
using ServiceStack.Web;
using ServiceStack.Host.Handlers;
using ServiceStack.Text;
namespace ServiceStack;
/// <summary>
/// Add a new API Handler at a custom route.
///
/// RawHttpHandlers.Add(ApiHandlers.Json("/api/{Request}")) => delegates /api/* requests to JSON Request Handler, e.g:
/// - /api/Hello => {"result":"Hello"}
/// - /api/Hello?name=World => {"result":"Hello, World"}
/// </summary>
public static class ApiHandlers
{
public static Func<IHttpRequest, HttpAsyncTaskHandler> Json(string apiPath) =>
Generic(apiPath, MimeTypes.Json, RequestAttributes.Reply | RequestAttributes.Json, Feature.Json);
public static Func<IHttpRequest, HttpAsyncTaskHandler> Jsv(string apiPath) =>
Generic(apiPath, MimeTypes.Jsv, RequestAttributes.Reply | RequestAttributes.Jsv, Feature.Jsv);
public static Func<IHttpRequest, HttpAsyncTaskHandler> Csv(string apiPath) =>
Generic(apiPath, MimeTypes.Csv, RequestAttributes.Reply | RequestAttributes.Csv, Feature.Csv);
public static Func<IHttpRequest, HttpAsyncTaskHandler> Xml(string apiPath) =>
Generic(apiPath, MimeTypes.Xml, RequestAttributes.Reply | RequestAttributes.Xml, Feature.Xml);
public static Func<IHttpRequest, HttpAsyncTaskHandler> Generic(string apiPath,
string contentType, RequestAttributes requestAttributes, Feature features)
{
var baseApiPath = GetBaseApiPath(apiPath);
var useApiPath = apiPath.LastLeftPart('/') + '/';
return req => {
// Don't handle OPTIONS CORS requests
if (req.HttpMethod == HttpMethods.Options)
{
var emitHandler = HostContext.GetPlugin<CorsFeature>()?.EmitGlobalHeadersHandler;
if (emitHandler != null)
return emitHandler;
return null;
}
var pathInfo = req.PathInfo;
if (pathInfo == baseApiPath || pathInfo.StartsWith(useApiPath))
{
// Add support for overriding content type with ext, e.g. .csv
var apiName = pathInfo == baseApiPath ? "" : pathInfo.LastRightPart('/');
if (string.IsNullOrEmpty(apiName))
{
var feature = HostContext.GetPlugin<PredefinedRoutesFeature>();
if (feature?.ApiIndex != null)
{
var ret = feature.ApiIndex(req);
return new CustomActionHandlerAsync(async (req, res) =>
{
res.ContentType = contentType;
var serializer = HostContext.ContentTypes.GetStreamSerializerAsync(contentType);
await serializer(req, ret, req.Response.OutputStream).ConfigAwait();
});
}
return new NotFoundHttpHandler();
}
var useContentType = contentType;
var useRequestAttrs = requestAttributes;
var useFeature = features;
if (apiName.IndexOf('.') >= 0)
{
var ext = apiName.RightPart('.');
apiName = apiName.LeftPart('.');
useContentType = HostContext.ContentTypes.GetFormatContentType(ext);
useRequestAttrs = RequestAttributes.Reply | ContentFormat.GetEndpointAttributes(useContentType);
useFeature = useContentType.ToFeature();
}
return new GenericHandler(useContentType, useRequestAttrs, useFeature) {
RequestName = apiName
};
}
return null;
};
}
public static string GetBaseApiPath(string apiPath)
{
if (string.IsNullOrEmpty(apiPath))
throw new ArgumentNullException(nameof(apiPath));
if (apiPath[0] != '/')
throw new ArgumentException("must start with '/'", nameof(apiPath));
if (!apiPath.EndsWith("/{Request}"))
throw new ArgumentException("must end with '/{Request}'", nameof(apiPath));
var baseApiPath = apiPath.LastLeftPart('/');
return baseApiPath;
}
public static HttpAsyncTaskHandler JsonEndpointHandler(string apiPath, string pathInfo)
{
var useContentType = MimeTypes.Json;
var useRequestAttrs = RequestAttributes.Reply | RequestAttributes.Json;
var useFeature = Feature.Json;
var apiName = pathInfo == apiPath ? "" : pathInfo.LastRightPart('/');
if (string.IsNullOrEmpty(apiName))
return new NotFoundHttpHandler();
if (apiName.IndexOf('.') >= 0)
{
var ext = apiName.RightPart('.');
apiName = apiName.LeftPart('.');
useContentType = HostContext.ContentTypes.GetFormatContentType(ext);
useRequestAttrs = RequestAttributes.Reply | ContentFormat.GetEndpointAttributes(useContentType);
useFeature = useContentType.ToFeature();
}
return new GenericHandler(useContentType, useRequestAttrs, useFeature) {
RequestName = apiName
};
}
}