Skip to content

HttpApi is a convinent framework to provide data by http, It can be the upgrating replacement for WebAPI. HttpApi 是一种便利的提供数据服务接口的框架,可作为 WebAPI 的升级方案

Notifications You must be signed in to change notification settings

surfsky/HttpApi

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

72 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

HttpApi

DotNet Framework version is here NetCore Framework version is here

1.Description

  • (01) HttpApi is a convinent framework to provide data by http, It is the upgrating replacement for WebAPI.
  • (02) HttpApi can export class function to http interface, eg.
http://.../HttpApi/TypeName/Method?p1=x&p2=x
  • (03) HttpApi can export page's method to http interface, eg.
http://.../Page1.aspx/GetData?page=1&rows=2&sort=abc&order=desc
http://.../Handler1.ashx/GetData?page=1&rows=2&sort=abc&order=desc
  • (04) HttpApi can auto create client javascript.
http://.../HttpApi/TypeName/js
  • (05) HttpApi can auto create api list page, api test page. eg.
HttpApi/TypeName/api
HttpApi/TypeName/apis
HttpApi/TypeName/Method$
  • (06) Caching: You can assign api result caching duration. And client can refresh cache by '_refresh=true' parameter.
  • (07) Auth: IP, Method, LoginStatus, UserName, UserRole, Token, and custom logic.
  • (08) Capsule: return standard APIResult object to client.
  • (09) Output configuration: You can config output format, such as enum, datetime, long number, error.
  • (10) Server site and client can assign api output data format, such as text, xml, json, file, image, base64image.
  • (11) Support nullable and default parameter.
  • (12) Support traffic control, see HttpApiAttribute.AuthTraffic
  • (13) Support upload file, see HttpApiAttribute.PostFile

2.Author

http://github.com/surfsky

3.Install

Nuget: install-package App.HttpApi
Nuget: install-package App.HttpApiCore

4.Usage

Skip to step 3 if use nuget to install httpapi.

(1) Import App.HttpApi.dll
(2) Config

netframework version

  <configSections>
    <section name="httpApi" type="App.HttpApi.HttpApiConfig, App.HttpApi"/>
  </configSections>
  <httpApi 
      formatEnum="Text" 
      formatIndented="Indented" 
      formatDateTime="yyyy-MM-dd" 
      formatLongNumber="Int64,UInt64,Decimal"
      formatLowCamel="false"
      errorResponse="APIResult" 
      typePrefix="App." 
      wrap="false" 
      language="en"
      />
  <system.webServer>
      <modules>
        <add name="HttpApiModule" type="App.HttpApi.HttpApiModule" />
      </modules>
  </system.webServer>

net core version

app.UseHttpApi(o =>                        // ÆôÓÃ HttpApi
{
    o.TypePrefix = "App.API.";
    o.FormatEnum = EnumFomatting.Int;
});

(3) Modify method, add [HttpApi] Attribute

namespace App
{
    public class Demo
    {
        [HttpApi("HelloWorld")]
        public static string HelloWorld(string info)
        {
           System.Threading.Thread.Sleep(200);
           return string.Format("Hello world! {0} {1}", info, DateTime.Now);
        }
    }
}

(4) Ok, Client can call this api by url:

http://...../HttpApi/Demo/HelloWorld?info=x

or test:

http://...../HttpApi/Demo/HelloWorld$

5.Senior guidline

(1) Control HttpApi output format

Web.Config
<configSections>
  <section name="httpApi" type="App.HttpApi.HttpApiConfig, App.HttpApi"/>
</configSections>
<httpApi 
  formatEnum="Text"                      // Decide how to export Enum: Text | Int
  formatIndented="Indented"              // Decide whether to beautify json output by and space indent and line break
  formatDateTime="yyyy-MM-dd"            // Decide how to export DateTime
  formatLowCamel="false"                 // Decide whether to use low camel for property name
  formatLongNumber="Int64,Decimal"       // Decide which number type to string, to avoiding javascript number precision error
  errorResponse="APIResult"              // Decide error output when catch exception: APIResult | HttpError
  typePrefix="App."                      // Url abbr support. eg. Raw url /HttpAPI/App.Base/Demo can change to the short path: /HttpApi/Base/Demo
  language="en"                          // Culture support: en, zh-CN
  />

(2) Auto create client javascript

<script src="http://.../HttpApi/Demo/js"></script>

You can add [Script] attrubute to class, to control the js content:

[Script(CacheDuration =0, ClassName ="Demo", NameSpace ="App")]

(3) Auto create api list, api test page.

http://..../HttpApi/Demo/api
http://..../HttpApi/Demo/HelloWorld$

You can add [History] attribute, to display api modify history. You can add [Param] attribute, to display api parameter infomation.

[History("2016-11-01", "SURFSKY", "modify A")]
public class Demo
{
    [HttpApi("HelloWorld", CacheSeconds=10)]
    [Param("info", "information")]
    public static string HelloWorld(string info)
    {
        ....
    }
}

Api list page

Api test page

(4) Caching

[HttpApi("Output system time", CacheSeconds=30)]
public DateTime GetTime()
{
    return System.DateTime.Now;
}

The api result will cache 30 seconds:

/HttpAPI/Common/GetTime

Add _refresh parameter if you want to refresh cache right now. It's useful when testing:

/HttpAPI/Common/GetTime?_refresh=true

(5) Control the output data type

Server site

[HttpApi("...", Type = ResponseType.JSON)]
[HttpApi("...", Type = ResponseType.XML)]
[HttpApi("...", Type = ResponseType.Text)]
[HttpApi("...", Type = ResponseType.Html)]
[HttpApi("...", Type = ResponseType.Javascript)]
[HttpApi("...", Type = ResponseType.Image)]
[HttpApi("...", Type = ResponseType.ImageBase64)]
[HttpApi("...", Type = ResponseType.TextFile,)]
[HttpApi("...", Type = ResponseType.BinaryFile)]

Client side

http://...../HttpApi/Demo/HelloWorld?_type=xml
<APIResult>
    <Result>True</Result>
    <Info>»ñÈ¡³É¹¦</Info>
    <CreateDt>2019-07-16 10:26:30</CreateDt>
    <Data>Hello world!</Data>
    <Extra/>
</APIResult>

(6) Auth

The usualy api security protection, and HttpApi solution:

  • Use Https to transport api data, to avoiding be listenned and modified.
  • Full open api: This kinds of api is only use in inner trusted system environment.
  • Fixed Token protected api: This kind of token is fixed string, such as appid.
  • Dynamic token protected api: Token is created by appid + appsecret + timestamp.
  • Need Login api: such as GetMyOrder.
  • Other limit: IP, Frequence, Action.

HttpAPI makes some AuthXXX properties to support api security.

[HttpApi("...", AuthVerbs="Get,Post")]      // check visit verb
[HttpApi("...", AuthLogin=true)]            // check user login status
[HttpApi("...", AuthUsers="A,B")]           // check user name
[HttpApi("...", AuthRoles="A,B")]           // check user role
[HttpApi("...", AuthIP=true)]               // check visit IP
[HttpApi("...", AuthToken=true)]            // check token
[HttpApi("...", AuthTraffic=1)]             // check traffic for: 1 times per second

Check login status, user name, user role

[HttpApi("Login")]
public string Login()
{
    AuthHelper.Login("Admin", new string[] { "Admins" }, DateTime.Now.AddDays(1));
    System.Threading.Thread.Sleep(200);
    return "Login success ";
}

[HttpApi("Sign out")]
public string Logout()
{
    AuthHelper.Logout();
    System.Threading.Thread.Sleep(200);
    return "Sign ok";
}

[HttpApi("User must login", AuthLogin=true)]
public string LimitLogin()
{
    System.Threading.Thread.Sleep(200);
    return "OK(Logined) ";
}

[HttpApi("User must be admin or kevin", AuthUsers = "Admin,Kevin")]
public string LimitUser()
{
    System.Threading.Thread.Sleep(200);
    return "OK(Limit Admin,Kevin) ";
}

[HttpApi("Use must has 'admins' role", AuthRoles = "Admins")]
public string LimitRole()
{
    System.Threading.Thread.Sleep(200);
    return "OK(Limit Admins) ";
}

AuthToken and AuthIP

You can check token and ip in custom way, eg.

public class Global : System.Web.HttpApplication
{
    protected void Application_Start(object sender, EventArgs e)
    {
        // HttpApi custom auth
        HttpApiConfig.Instance.OnAuth += (ctx, method, attr, token) =>
        {
            if (attr.AuthIP && !CheckIP(ip))
                throw new HttpApiException("This ip is forbidden", 401);
            if (attr.AuthToken && !CheckToken(token))
                throw new HttpApiException("Please check token", 401);
            if (attr.Log)
                Logger.Log(...);
            // Other auth logic, such as visit frequence.
            // Throw HttpApiException if auth fail.
        };
    }
}

AuthTraffic

HttpApi supports traffic control. To enable this capability, just set HttpApiAttribute.AuthTraffic=n (n means visit times per second). The engine will count and detect the visit ip and url. If the traffic is too heavy, the engine will abort the connection for a long time (Setted in HttpApiConfig.Instance.BanMinutes). This capability is offen openned for login api to protect website security.

[HttpApi("User login", AuthTraffic=1)]
public string Login()
{
    AuthHelper.Login("Admin", new string[] { "Admins" }, DateTime.Now.AddDays(1));
    System.Threading.Thread.Sleep(200);
    return "Login success";
}

If you refresh the login api page too quickly, you will see the unreachable page error for a long time.

(7) Upload

HttpApi supports upload file. To enable this capability, just set HttpApiAttribute.PostFile=true, the engine will auto create test page with a file input field.

[HttpApi("UploadFile", PostFile=true)]
public APIResult Up(string filePath, string fileName)
{
    ...
    if (HttpContext.Current.Request.Files.Count == 0)
        return new APIResult(false, "File doesn't exist", 11);
    Asp.Request.Files[0].SaveAs(path);
    return new APIResult(true, url);
}

The test page may be:

(8) Uniform data format: APIResult

HttpApi support uniform api result format to simply client calling.

[HttpApi("Ouput system datetime")]
public APIResult GetTime()
{
    return new APIResult(true, "OK", System.DateTime.Now);
}

Then the output maybe

{
    Result: true,
    Info: "OK",
    CreateDt: "2019-07-16 10:24:14",
    Data: '2019-01-01',
    Extra: {...}
}

(8) Other HttpApiAttribute properties

public string Description { get; set; }
public string Example { get; set; }
public string Remark { get; set; }
public string MimeType { get; set; }
public string FileName { get; set; }
public bool Wrap { get; set; } = false;
public ApiStatus Status { get; set; }
public bool PostFile {get; set;}

6. More examples

[HttpApi("Json Wrapper", Wrap = true)]
public static object TestWrap()
{
    return new { h = "3", a = "1", b = "2", c = "3" };
}

[HttpApi("Default paramter", Status = ApiStatus.Delete, AuthVerbs ="GET")]
public static object TestDefaultParameter(string p1, string p2="a")
{
    return new { p1 = p1, p2 = p2};
}

[HttpApi("Exception Test")]
public static object TestError()
{
    int n = 0;
    int m = 1 / n;
    return true;
}

[HttpApi("Auth verb", AuthVerbs ="Post")]
public static string TestVerbs()
{
    return HttpContext.Current.Request.HttpMethod;
}

[HttpApi("Return enum")]
public static Sex TestEnum()
{
    return Sex.Male;
}

//---------------------------------------------
// Other basic data type
//---------------------------------------------
[HttpApi("plist file", CacheSeconds = 30, MimeType="text/plist", FileName="app.plist")]
public string GetFile(string info)
{
    System.Threading.Thread.Sleep(200);
    return string.Format("This is plist file demo! {0} {1}", info, DateTime.Now);
}

[HttpApi("date time", CacheSeconds=30)]
public DateTime GetTime()
{
    return System.DateTime.Now;
}

[HttpApi("DataTable")]
public DataTable GetDataTable()
{
    DataTable dt = new DataTable("test");
    dt.Columns.Add("column1");
    dt.Columns.Add("column2");
    dt.Rows.Add("a1", "b1");
    dt.Rows.Add("a2", "b2");
    return dt;
}

[HttpApi("DataRow")]
public DataRow GetDataRow()
{
    DataTable dt = new DataTable("test");
    dt.Columns.Add("column1");
    dt.Columns.Add("column2");
    dt.Rows.Add("a1", "b1");
    dt.Rows.Add("a2", "b2");
    return dt.Rows[0];
}

[HttpApi("Dictionary")]
public IDictionary GetDictionary()
{
    var dict = new Dictionary<int, Person>();
    dict.Add(0, new Person() { Name = "Marry" });
    dict.Add(1, new Person() { Name = "Cherry" });
    return dict;
}

[HttpApi("Image", CacheSeconds=60)]
public Image GetImage(string text)
{
    Bitmap bmp = new Bitmap(200, 200);
    Graphics g = Graphics.FromImage(bmp);
    g.DrawString(
        text, 
        new Font("Arial", 16, FontStyle.Bold), 
        new SolidBrush(Color.FromArgb(255, 206, 97)), 
        new PointF(5, 5)
        );
    return bmp;
}


//---------------------------------------------
// Class
//---------------------------------------------
[HttpApi("father:{Name:'Kevin', Birth:'1979-12-01', Sex:0};")]
public Person CreateGirl(Person father)
{
    return new Person()
    {
        Name = father.Name + "'s dear daughter",
        Birth = System.DateTime.Now,
        Sex = Sex.Female,
        Father = father
    };
}

[HttpApi("null")]
public static Person CreateNull()
{
    return null;
}

[HttpApi("Output class object")]
public static Person GetPerson()
{
    return new Person() { Name = "Cherry" };
}


[HttpApi("Output Xml", Type=ResponseType.XML)]
public static Person GetPersonXml()
{
    return new Person() { Name = "Cherry" };
}

[HttpApi("Output class, and wrap with APIResult", Wrap =true)]
public static Person GetPersonDataResult()
{
    return new Person() { Name = "Kevin" };
}

[HttpApi("Output APIResult")]
public static APIResult GetPersons()
{
    var persons = new List<Person>(){
        new Person(){ Name="Kevin", Sex=Sex.Male, Birth=new DateTime(2000, 01, 01)},
        new Person(){ Name="Cherry", Sex=Sex.Female, Birth=new DateTime(2010, 01, 01)}
    };
    return new APIResult(true, "", persons);
}

7. Project motivation

  • Basic motivation: (1) Simplify api coding for http server; (2) Auto create client calling javascript
  • And more complex functions, such as auth, security, caching, format, exception, uniform api result, etc.
  • WebAPI has many limits: http://blog.csdn.net/leeyue_1982/article/details/51305950
  • So I create this project, and maintain it for so many years.

8.Snapshots

Api define

Api output(defautl is json)

Api output xml

Token demo

Auth demo

9.Roadmap

  • Long time connect
  • XML format control: property/field, indent, case...

10.History

Chinese readme file is here

11. Thanks

Buy me a coffee if you like this framework, thank you.

AliPay

WechatPay

Paypal

About

HttpApi is a convinent framework to provide data by http, It can be the upgrating replacement for WebAPI. HttpApi 是一种便利的提供数据服务接口的框架,可作为 WebAPI 的升级方案

Resources

Stars

Watchers

Forks

Packages

No packages published