用.NetCore 控制台提供简单http服务-新闻详情

用.NetCore 控制台提供简单http服务


发布时间:2020-07-09责任编辑:满帅 浏览:1948


为什么不用asp.netcore 呢?

如果我只需要一点向外提供Web服务的功能呢。

比如,托管程序的更新包,或者只是显示一张图片

 

主角:WebListener

WebListener 通过Nuget 包安装,它比HttpListener 要新。具体区别,忘了,可以Google查一下。

当然,.NetFramework 也行。

启动

 

var _webListener = new WebListener();

_webListener.Settings.UrlPrefixes.Add($"http://*:8088");

_webListener.Start();

 

监听请求

 

Thread thread = new Thread(HttpHandler);

thread.Start();

 

 

        private async void HttpHandler()

        {

            while (_listening)

            {

                RequestContext context = null;

                try

                {

                    context = await _webListener.AcceptAsync();

                } catch (Exception ex)

                {

                    ex = ex.Demystify();

                    _logger.LogError($"an error occur due AcceptAsync request :> {ex.Message}");

                    continue;

                }

 

                ThreadPool.QueueUserWorkItem((_) =>

                {

                    var segments = context.Request.RawUrl.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);

                    if (segments.Length > 0)

                    {

                        string methodName = segments[0];

                        string[] strParams = segments.Skip(1).ToArray();

 

                        var method = GetType().GetMethods()

                    .Where(mi => mi.GetCustomAttributes(true)

                    .Any(attr => attr is Mapping map && map.Map.Equals(methodName,StringComparison.OrdinalIgnoreCase)))

                    .FirstOrDefault();

 

                        if (method != null)

                        {

                            try

                            {

                                List<object> @params = method

                                .GetParameters()

                                .Skip(1)

                                .Select((p, i) => Convert.ChangeType(strParams[i], p.ParameterType)).ToList();

 

                                @params.Insert(0, context);

                                method.Invoke(this, @params.ToArray());

                            } catch (Exception ex)

                            {

                                context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;

                                context.Response.ReasonPhrase = ex.Message;

                            }

 

                        }

                        else

                        {

                            context.Response.StatusCode = (int)HttpStatusCode.NotFound;

                        }

 

                    }

                    else

                    {

                        context.Response.StatusCode = (int)HttpStatusCode.NotFound;

                    }

 

                    context.Dispose();

 

                });

 

            }

        }

 

 

 

处理请求

监听到的请求会找到带有Mapping特性的方法来处理,Map字段代表请求中第一个路径的名称比如http://server/image

 

 [AttributeUsage(AttributeTargets.Method)]

    class Mapping :Attribute

    {

        public string Map;

        public Mapping(string s)

        {

            Map = s;

        }

    }

 

  [Mapping("image")]

        public async void HttpImageHandler(RequestContext context, string path)

        {

 

            

            string decodePath = HttpUtility.UrlDecode(path);

 

            string filePath = Path.Combine(_appConfigOptions.Value?.AvatarStorePath,

                decodePath);

 

            if (File.Exists(filePath))

            {

                await context.Response.SendFileAsync(filePath, 0, null, context.DisconnectToken);

            }

            else

            {

                context.Response.StatusCode = (int)HttpStatusCode.NotFound;

            }

        }

 

 

不算复杂,简单的Web服务和超简单的路由就实现了。


外包部供稿