How Well Do You Define Your APIs?

How Well Do You Define Your APIs?

API stands for Application Programming Interface, but have you ever wondered how the concept originated? Let’s take a journey back in history.

In today’s world, where technology is integral to daily life, businesses heavily rely on various technologies to operate efficiently and expand globally. To achieve these goals, businesses often adopt multiple systems to manage their operations. However, integrating and maintaining these systems can be both expensive and labor-intensive.

Recognizing this challenge, industry giants like Salesforce, eBay, and Amazon introduced a groundbreaking concept in the early 2000s: APIs. These APIs acted as bridges that enabled systems to communicate and perform operations without requiring native implementation. Between 2000 and 2004, APIs revolutionized online business. Salesforce, eBay, and Amazon launched their APIs in February 2000, November 2000, and July 2002, respectively, solidifying their dominance.

In 2000, Roy Fielding introduced the concept of REST (Representational State Transfer), a flexible architectural style for designing web services. REST works independently of HTTP and other protocols, supporting hypermedia beyond just XML.

This brief overview sets the stage for discussing how developers define APIs. Let’s delve into key components that contribute to well-defined APIs.

How to Define APIs Effectively

Having spent much of my career working with .NET technologies, I appreciate how Microsoft continuously updates its capabilities. While my examples focus on .NET, the principles apply universally across languages, differing only in syntax.

You will find the sample code below or a reference link with much more details on implementation.

When developing an API, it is essential to ensure resilience and adaptability to recover from failures seamlessly.

Key Components of a Well-Defined API

1.????? Validation of user input should not be the only responsibility of the user interface. In the modern world, many processes run with zero UI and must validate each entry. You can use Fluent Library, which is one of the good options to apply your validation in your API. You can read more about Fluent Validation here

Here is an example of a Fluent Validation for your Employee model:

public class EmployeeValidator : AbstractValidator<Employee>
{
  public EmployeeValidator ()
  {
    RuleFor(x => x.FirstName).NotEmpty().WithMessage("Please specify a first name");
    RuleFor(x => x.LastName).NotEmpty().WithMessage("Please specify a last name");
    RuleFor(x => x.Age).LessThan(80);
  }
}        

2. API Versioning manages changes to an API over time. As requirements evolve, so does implementation. However, maintaining compatibility with existing clients while rolling out updates is crucial. Versioning strategies include:

a). URL Versioning: You can achieve this versioning as parameters example: https://www.example.com/v1/hello or https://www.example.com/hello?version=v1

b). Header Versioning: Embedding version information in HTTP headers for a cleaner URL structure.

To implement API version in .Net Core project follow below steps:

Install these Nuget packages :

1. Asp.Versioning.Http
2. Asp.Versioning.Mvc (this one if you are using Controllers)
3. Asp.Versioning.Mvc.ApiExplorer (this particular one if you want to use the support of swagger)        

in program.cs file use below code:

builder.Services.AddApiVersioning(options =>
{
    options.DefaultApiVersion = new Asp.Versioning.ApiVersion(1);
    options.ApiVersionReader = ApiVersionReader.Combine(
            new UrlSegmentApiVersionReader(),
            new HeaderApiVersionReader("X-ApiVersion"));
}).AddApiExplorer(options =>
    {
        options.GroupNameFormat = "'v'V";
        options.SubstituteApiVersionInUrl = true;
    });        

For details on the implementation of ASP.NET Core, refer to this blog.


3. Resilience Failures are inevitable in HTTP communication. It is not necessary to have an issue with your API definition only. This causes service interruption and may lead to much more serious transactional issues. Implement strategies like:

a). Retry: Retry failed requests a set number of times before logging errors.

b). Fallback: Define alternative actions for failed requests.

c). Circuit Breaker: Halt communication during service outages and resume once recovery is detected.

Use libraries like Polly to implement these patterns quickly. You can install these two packages to have your API resilient from failure which runs on top of Polly.

1. Microsoft.Extensions.Resilience
2. Microsoft.Extensions.Http.Resilience        

However, you can implement this in many different and better ways but you can start with simple implementation. In your program.cs file, register the service using the following code

builder.Services.AddResiliencePipeline("retry", option =>
{
    option .AddRetry(new RetryStrategyOptions
    {
        Delay = TimeSpan.FromSeconds(1),
        MaxRetryAttempts = 2,
        BackoffType = DelayBackoffType.Exponential,
        UseJitter = true
    });
});        

Learn more about resilience in .NET applications.


4. Health Checks Monitoring API health helps detect and prevent failures, optimize performance, and enhance security. Automate health checks using tools from the

Microsoft API health monitoring guide.

You can register your health check service in program.cs by adding below lines of code

builder.Services.AddHealthChecks();        

then define your mapping

app.MapHealthChecks("health");        

5. Caching Optimize performance by storing frequently accessed data. API performance is key to acceptance of usage by the world. When I was working on one of eCommerce-based websites, I got a knowledge about a statistic that user lose interest if their web page response is above 3 seconds and they move away. The caching strategy plays an important role in determining how you can fetch the data and reuse it. You can use cache either on the server side or the client side. Client-side caching typically stores the data in your web browser and does not need to request the server and re-download the data to the client. Server Cache occurs on the server where computed data is already stored and available upon request. So basically saves computational time on subsequent requests. You can control caching by the cache-control header of the http request where you can set the expiration date. Based on your requirement you can decide where you would like store your cache among them:

a). Client-Side Cache: Saves data in the browser to avoid redundant server requests.

b). Server-Side Cache: Stores computed data on the server for faster subsequent requests.

You can cache your data in many ways like In-memory, Distributed, Output, Hybrid cache. The following link help you understand them in depth.

https://learn.microsoft.com/en-us/aspnet/core/performance/caching/memory?view=aspnetcore-9.0

When you use your browser's developer tool, you can easily identify the cached data of any website by analyzing networking tab. You may see something like this having assigned caching parameters

? accept-ranges: bytes
? age: 27752
? alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
? cache-control: public, immutable, max-age=31536000
? content-encoding: gzip
? content-length: 108711
? content-type: text/javascript; charset=UTF-8

        

6. Pagination Handle large datasets efficiently by loading data in smaller chunks. This is the time when we depend heavily on data because we need it for our analytics, prediction model, AI processing etc. We cannot skip or ignore any data from consumption. API pagination helps you to load your data partially which you can continue loading on your consecutive request. There are many pagination methods you can use but one of the simplest and easiest is Offset Pagination where you can set your limit of records and you can keep requesting the next set of records.

In offset Pagination, you pass your paging-related parameter (like GET /items?limit=10&offset=20) to your get method like

public async Task<IEnumerable<Employee>> GetEmployeeAsync(int? page, string sort, string? filter, int pageSize);        

And implement logic to return only requested rows. One possible ways to embed the following line with parameters value to your

SELECT SQL query OFFSET @Offset ROWS FETCH NEXT @PageSize ROWS ONLY        

Read more about API pagination.


7. Logging Logs provide insights into API health and behavior. Key log types:

a). Access Logs: Track request sources and patterns.

b). Error Logs: Record detailed errors for debugging.

c). Performance Logs: Monitor response times to gauge API efficiency.

d). Security Logs: Log authentication attempts to identify potential threats.

A library called

provides diagnostic logging to files/databases etc. To use Serilog you can use very friendly documentation here [Serilog]

Log monitoring can be easily done by tools like Seq, Datadog, Dynatrace, etc and they offer very rich options for monitoring and alerting.


8. Authentication Secure your APIs with robust authentication mechanisms. Native .NET libraries are reliable, but solutions like Keycloak or Azure App Registration offer enhanced security. Find here Github link, an example to secure your API using Azure


9. Rate Limiting Prevent misuse by limiting API calls per user. Possibly you will see the http status code 429 (Too Many Connections) when you try to call more than the limit defined. Rate-limiting strategies include:

a). Fixed Window: Restrict requests within a set timeframe.

b). Sliding Window: Allocate requests in segments of time.

c). Token Bucket: Use tokens to cap requests.

d). Concurrency: Limit simultaneous connections.

Learn more about rate-limiting in ASP.NET Core.


10. API Gateways - Why we use API gateway? Many of us are confused between API and API gateway. Where API is final endpoints which takes direct request and return response after some computation on servers, API gateway is just act as bridge between clients and services. Consider a scenario, you have a dashboard which uses total 10 APIs to show the data and you need all of them as minimum but if you have same dashboard in mobile application then probably you won't need all 10 APIs at that moment because of limitation of view size. Mobile user may need only 5 APIs to consume because 4 cannot be visible on mobile screen. API gateway can decide, how many API endpoints you wanted to expose as per the client. You can also use API gateway for entry point where you can add security, rate limit, control access, versioning etc.

Explore open-source options like YARP and Ocelot for .NET API gateways.


11. Content Delivery Network (CDN) CDNs distribute static content (like files, images) across geographically distributed servers, reducing latency and improving performance.


12. Swagger Having API documentation is most effective when someone wishes to consume your API. Swagger creates interactive API documentation. Interactive means you can quickly execute some nice built API interface just to see, how API works.

Install the packages

1. Swashbuckle.AspNetCore
2. Swashbuckle.AspNetCore.Swagger
3. Swashbuckle.AspNetCore.SwaggerUI        
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Employee API", Version = "v1" });
});        

Important points worth mentioning:

  1. Partial Responses Large resources can be delivered in smaller chunks using the HTTP 206 Partial Content status code. Use headers like Content-Range to specify chunk sizes.

HTTP/1.1 206 Partial Content

Accept-Ranges: bytes
Content-Type: image/jpeg
Content-Length: 2500
Content-Range: bytes 0-2499/4580
...        

2. Content Negotiation: This process where a server determines the best format to return a response to a client based on the client’s request headers, allowing the client to specify their preferred data format like Json, XML.

builder.Services.AddControllers(options => { ??? options.RespectBrowserAcceptHeader = true; }).AddXmlSerializerFormatters();        

use the above code to send the accept header as application/xml.

3. SOAP (Simple Object Access Protocol): It is a protocol used for exchanging structured information in the implementation of web services in computer networks. SOAP uses XML to encode its messages and relies on other application layer protocols such as HTTP or SMTP for message negotiation and transmission.

4. Http is stateless: If you send any request over HTTP, it cannot remember your previous request. So make sure you do extra stuff if you want to persist values during your HTTP calls.

5. Connection Pool Exhaustion: On high load, if your application keeps creating new connections (by using var client = new HttpClient();), the connection will exhaust very quickly. To resolve this, use IHttpClientFactory to create a HttpClient instance.

6. SOLID: While designing your API, you need to make sure you follow the SOLID principle as best practices for writing your code.


Conclusion

A well-defined API serves as the cornerstone of seamless integration and efficient communication in modern software ecosystems. By adhering to clear standards, robust documentation, and thoughtful design principles, APIs enhance scalability, maintainability, and usability across diverse platforms. A well-structured API not only empowers developers to build and innovate with confidence but also ensures a superior user experience by enabling reliable and secure interactions. As businesses increasingly rely on interconnected systems, the importance of well-defined APIs in driving operational efficiency and fostering technological collaboration cannot be overstated.

要查看或添加评论,请登录

Rajeev Singh的更多文章

  • Your local AI Chat

    Your local AI Chat

    Are you concern about your data security and also wanted to use power of ChatGPT kind of great tool but fearing to give…

  • Master-Slave Databases

    Master-Slave Databases

    When data grows in your application, the performance deteriorates and that's true. You can't stop data from developing…

  • Sharding

    Sharding

    As you know, any system backbone is data and data grows everyday. According to statistics, by year 2028, the projected…

  • HTTP Protocol

    HTTP Protocol

    What is HTTP and how it works? Http developed by Tim Berners-Lee when he was in CERN year 1989-1991. Everyone has…

    1 条评论
  • Change Data Capture (CDC)

    Change Data Capture (CDC)

    Change data capture utilizes the SQL Server Agent to log insertions, updates, and deletions occurring in a table. So…

  • On-Prem Database Deployment (DevOps)

    On-Prem Database Deployment (DevOps)

    Introduction If you are a developer and in the tech world, you must have heard about databases. This is the heart of…

    1 条评论
  • Docker - Easy Way

    Docker - Easy Way

    Definition Docker is a powerful tool that provides a platform to package solutions for deployment. We can think like a…

    1 条评论

社区洞察

其他会员也浏览了