Movatterモバイル変換


[0]ホーム

URL:


Packt
Search iconClose icon
Search icon CANCEL
Subscription
0
Cart icon
Your Cart(0 item)
Close icon
You have no products in your basket yet
Save more on your purchases!discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Profile icon
Account
Close icon

Change country

Modal Close icon
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletter Hub
Free Learning
Arrow right icon
timerSALE ENDS IN
0Days
:
00Hours
:
00Minutes
:
00Seconds
Home> Web Development> Microservices> Building Python Microservices with FastAPI
Building Python Microservices with FastAPI
Building Python Microservices with FastAPI

Building Python Microservices with FastAPI: Build secure, scalable, and structured Python microservices from design concepts to infrastructure

Arrow left icon
Profile Icon Sherwin John C. Tragura
Arrow right icon
$33.99$37.99
Full star iconFull star iconFull star iconHalf star iconEmpty star icon3.9(9 Ratings)
eBookAug 2022420 pages1st Edition
eBook
$33.99 $37.99
Paperback
$46.99
Subscription
Free Trial
Renews at $19.99p/m
Arrow left icon
Profile Icon Sherwin John C. Tragura
Arrow right icon
$33.99$37.99
Full star iconFull star iconFull star iconHalf star iconEmpty star icon3.9(9 Ratings)
eBookAug 2022420 pages1st Edition
eBook
$33.99 $37.99
Paperback
$46.99
Subscription
Free Trial
Renews at $19.99p/m
eBook
$33.99 $37.99
Paperback
$46.99
Subscription
Free Trial
Renews at $19.99p/m

What do you get with eBook?

Product feature iconInstant access to your Digital eBook purchase
Product feature icon Download this book inEPUB andPDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature iconDRM FREE - Read whenever, wherever and however you want
Product feature iconAI Assistant (beta) to help accelerate your learning
OR

Contact Details

Modal Close icon
Payment Processing...
tickCompleted

Billing Address

Table of content iconView table of contentsPreview book icon Preview Book

Building Python Microservices with FastAPI

Setting Up FastAPI for Starters

In any software development work, it is always important to first know the business requirement of the project and the appropriate framework, tools, and deployment platform to use before pursuing the task. Frameworks that are easy to understand and use, seamless during coding, and within standards are always picked because of the integrity they provide to solve problems without risking too much development time. And a promising Python framework calledFastAPI, created bySebastian Ramirez, provides experienced developers, experts, and enthusiasts the best option for buildingREST APIs and microservices.

But before proceeding to the core details of building microservices using FastAPI, it is best to first learn the building blocks of this framework, such as how it captures clients’ requests, how it builds the rules for each HTTP method, and how it manages HTTP responses. Learning the basic components is always essential to know the strengths and weaknesses of the framework and to what extent we can apply FastAPI to solve different enterprise-grade and microservices-related problems.

Thus, in this chapter, we’re going to have a walkthrough of the basic features of FastAPI by covering the following main topics:

  • The setup of the development environment
  • Initialization and configuration of FastAPI
  • Design and implementation of the REST APIs
  • Managing user requests and server response
  • Handling form parameters
  • Handling cookies

Technical requirements

The software specimen for this chapter is a prototypical administrator-managedonline academic discussion forum, which is an academic discussion hub where alumni, teachers, and students can exchange ideas. The prototype is working but it is open for changes, so you can tweak the code while reading this chapter. It is not designed to use any database management system, but all the data is temporarily stored in various Python collections. All the applications in this book are compiled and run usingPython 3.8. Codes are all uploaded athttps://github.com/PacktPublishing/Building-Python-Microservices-with-FastAPI/tree/main/ch01.

Setting up the development environment

The FastAPI framework isa fast, seamless, and robust Python framework but can onlywork on Python versions3.6 andabove. TheIntegrated Development Environment (IDE) used in this reference isVisual Studio Code (VS Code), whichis an open source toolthat we can download from this site:https://code.visualstudio.com/. Just be sure to install the VSC extensions such asPython,Python for VS Code,Python Extension Pack,Python Indent, andMaterial Icon Theme to provide your editor syntax checking, syntax highlighting, and other editor support.

After the successful installation of Python and VS Code, we can now install FastAPI using a terminal console. To ensure correct installation, first update Python’s package installer (pip) by running this command:

python -m pip install --upgrade pip

Afterward, we install the framework by running this series of commands:

pip install fastapipip install uvicorn[standard]pip install python-multipart

Important note

If you need to install the complete FastAPI platform, including all optional dependencies, the appropriate command ispip install fastapi[all]. Likewise, if you want to install and utilize the full-blownuvicorn server, you should run thepip install uvicorn command. Also, install thebcrypt module for encryption-related tasks.

At this point, youshould have installed allthe needed FastAPImodule dependencies from thepydantic andstarlette module components in your Python environment. Furthermore, thepython-multipart moduleis required to create a REST API that handles form parameters. The installeduvicorn, however, is an ASGI-basedserver that will run your FastAPI applications. TheAsynchronous Server Gateway Interface (ASGI) server that FastAPI uses makes it the fastest Python framework at the time of writing. Theuvicorn server has the capability to run both synchronous and asynchronous services.

After the installation and configuration of the essential tools, modules, and IDE, let us now start our first API implementation using the framework.

Initializing and configuring FastAPI

Learning howto create applications using FastAPI is easy and straightforward. A simpleapplication can be created just by creating amain.py file inside your/ch01 project folder. In ouronline academic discussion forum, for instance, the application started with this code:

from fastapi importFastAPIapp = FastAPI()

This initializes the FastAPI framework. The application needs to instantiate the coreFastAPI class from thefastapi module and useapp as the reference variable to the object. Then, this object is used later as a Python@app decorator, which provides our application with some features such asroutes,middleware,exception handlers, andpath operations.

Important note

You can replaceapp with your preferred but valid Python variable name, such asmain_app,forum, ormyapp.

Now, your application is ready to manage REST APIs that are technically Python functions. But todeclare them as REST service methods, we need to decorate themwith the appropriate HTTP request method provided by the path operation@app decorator. This decorator contains theget(),post(),delete(),put(),head(),patch(),trace(), andoptions() path operations, which correspond to the eight HTTP request methods. And thesepath operations are decorated or annotated on top of the Python functions that we want to handle the request and response.

In our specimen, the first sample that the REST API created was this:

@app.get("/ch01/index")def index():    return {"message": "Welcome FastAPI Nerds"}

The preceding is aGET API service method that returns aJSON object. To locally run our application, we need to execute the following command:

uvicorn main:app --reload

This command will load the forum application to the uvicorn live server through the application’smain.py file with FastAPI object referencing. Live reload is allowed by adding the--reload option, which enables the restart of the development server whenever there are changes in the code.

Figure 1.1 – The uvicorn console log

Figure 1.1 – The uvicorn console log

Figure 1.1 shows that uvicorn useslocalhost to run the application with the default port8000. Wecan access our index page throughhttp://localhost:8000/ch01/index. Tostop the server, you just need to press theCtrl +C keyboard keys.

After running our first endpoint, let us now explore how to implement the other types of HTTP methods, namelyPOST,DELETE,PUT, andPATCH.

Designing and implementing REST APIs

TheRepresentation State Transfer (REST) API makes up the rules, processes, and tools that allowinteraction amongmicroservices. These are methodservices that are identified and executed through their endpoint URLs. Nowadays, focusing on API methods before building a whole application is one of the mostpopular and effective microservices design strategies. This approach, called anAPI-first microservices development, focuses first on the client’s needs and then later identifies what API service methods we need to implement for these client requirements.

In ouronline academic discussion forum app, software functionality such asuser sign-up,login,profile management,message posting, andmanaging post replies are some of the crucial needs we prioritized. In a FastAPI framework, these features are implemented as services using functions that are defined using Python’sdef keyword, with the association of the appropriate HTTP request method through thepath operations provided by@app.

Thelogin service, which requiresusername andpassword request parameters from the user, is implemented as aGET API method:

@app.get("/ch01/login/")deflogin(username: str, password: str):    if valid_users.get(username) == None:        return {"message": "user does not exist"}    else:        user = valid_users.get(username)        if checkpw(password.encode(),                    user.passphrase.encode()):            return user        else:            return {"message": "invalid user"}

Thislogin service uses bcrypt’scheckpw() function to check whether the password of the useris valid. Conversely, thesign-up service, whichalso requires user credentials from the client in the form of request parameters, is created as aPOST API method:

@app.post("/ch01/login/signup")defsignup(uname: str, passwd: str):    if (uname == None and passwd == None):        return {"message": "invalid user"}    elif not valid_users.get(uname) == None:        return {"message": "user exists"}    else:        user = User(username=uname, password=passwd)        pending_users[uname] = user        return user

Among theprofile management services, the followingupdate_profile() service serves as aPUT API service, which requires the user to use an entirely new model object for profile information replacement and the client’s username to serve as the key:

@app.put("/ch01/account/profile/update/{username}")defupdate_profile(username: str, id: UUID,                      new_profile: UserProfile):    if valid_users.get(username) == None:        return {"message": "user does not exist"}    else:        user = valid_users.get(username)        if user.id == id:            valid_profiles[username] = new_profile            return {"message": "successfully updated"}        else:            return {"message": "user does not exist"}

Not allservices that carry out updatesarePUT API methods, such as the followingupdate_profile_name() service, which only requires the user to submit a new first name, last name, and middle initial for partial replacement of a client’s profile. This HTTP request, which is handier and more lightweight than a full-blownPUT method, only requires aPATCH action:

@app.patch("/ch01/account/profile/update/names/{username}")defupdate_profile_names(username: str, id: UUID,                           new_names: Dict[str, str]):    if valid_users.get(username) == None:        return {"message": "user does not exist"}    elif new_names == None:        return {"message": "new names are required"}    else:        user = valid_users.get(username)        if user.id == id:            profile = valid_profiles[username]            profile.firstname = new_names['fname']            profile.lastname = new_names['lname']            profile.middle_initial = new_names['mi']            valid_profiles[username] = profile            return {"message": "successfully updated"}        else:            return {"message": "user does not exist"}

The lastessential HTTP services thatwe included before building the application are theDELETE API methods. We use these services to delete records or information given a unique identification, such asusername and a hashedid. An example is the followingdelete_post_discussion() service that allows a user to delete a posted discussion when given a username and the UUID (Universally Unique Identifier) of the posted message:

@app.delete("/ch01/discussion/posts/remove/{username}")defdelete_discussion(username: str, id: UUID):    if valid_users.get(username) == None:        return {"message": "user does not exist"}    elif discussion_posts.get(id) == None:        return {"message": "post does not exist"}    else:        del discussion_posts[id]         return {"message": "main post deleted"}

All path operations require a unique endpoint URL in thestr format. A good practice is to start all URLs with the same top-level base path, such as/ch01, and then differ when reaching their respective subdirectories. After running the uvicorn server, we can check and validate whether all our URLs are valid and running by accessing the documentationURL,http://localhost:8000/docs. This path will show us aOpenAPI dashboard, as shown inFigure 1.2, listing all the API methods created for the application. Discussions on the OpenAPI will be covered inChapter 9, Utilizing Other Advanced Features.

Figure 1.2 – A Swagger OpenAPI dashboard

Figure 1.2 – A Swagger OpenAPI dashboard

After creatingthe endpoint services, let us scrutinize how FastAPI manages its incoming request body and the outgoing response.

Managing user requests and server response

Clients can pass their request data to FastAPI endpoint URLs through path parameters, queryparameters, or headers to pursue service transactions. There arestandards and ways to use these parameters to obtain incoming requests. Depending on the goal of the services, we use these parameters to influence and build the necessary responses the clients need. But before we discuss these various parameter types, let us explore first how we usetype hinting in FastAPI’s local parameter declaration.

Parameter type declaration

All requestparameters are required to be type-declared in the method signature of the service method applying thePEP 484 standard calledtype hints. FastAPI supports common typessuch asNone,bool,int, andfloat and container types such aslist,tuple,dict,set,frozenset, anddeque. Other complex Python types such asdatetime.date,datetime.time,datetime.datetime,datetime.delta,UUID,bytes, andDecimal are also supported.

The framework also supports the data types included in Python’styping module, responsible fortype hints. These data types are standard notations for Python and variable typeannotations that can help to pursue type checking and model validation during compilation, such asOptional,List,Dict,Set,Union,Tuple,FrozenSet,Iterable, andDeque.

Path parameters

FastAPI allows youto obtain request data from the endpoint URL of an API througha path parameter or path variable that makes the URL somewhat dynamic. This parameter holds a value that becomes part of a URL indicated by curly braces ({}). After setting off these path parameters within the URL, FastAPI requires these parameters to be declared by applyingtype hints.

The followingdelete_user() service is aDELETE API method that uses ausername path parameter to search for a login record for deletion:

@app.delete("/ch01/login/remove/{username}")def delete_user(username: str):    if username == None:    return {"message": "invalid user"}else:    del valid_users[username]    return {"message": "deleted user"}

Multiple path parameters are acceptable if the leftmost variables are more likely to be filled with values than the rightmost variables. In other words, the importance of the leftmost path variables will make the process more relevant and correct than those on the right. This standard is applied to ensure that the endpoint URL will not look like other URLs, which might cause some conflicts and confusion. The followinglogin_with_token() service follows this standard, sinceusername is a primary key and is as strong as, or even stronger than, its next parameter,password. There is an assurance that the URL will always look unique every time the endpoint is accessed becauseusername will always be required, as well aspassword:

@app.get("/ch01/login/{username}/{password}")def login_with_token(username: str,password:str,                      id: UUID):    if valid_users.get(username) == None:        return {"message": "user does not exist"}    else:        user = valid_users[username]        if user.id == id and checkpw(password.encode(),                  user.passphrase):            return user        else:            return {"message": "invalid user"}

Unlike other web frameworks, FastAPI is not friendly with endpoint URLs that belong to base paths ortop-level domain paths with different subdirectories. Thisoccurrence happens when we have dynamic URL patterns that look the same as the other fixed endpoint URLs when assigned a specific path variable. These fixed URLs are implemented sequentially after these dynamic URLs. An example of these are the following services:

@app.get("/ch01/login/{username}/{password}")def login_with_token(username: str,password:str,                      id: UUID):    if valid_users.get(username) == None:        return {"message": "user does not exist"}    else:        user = valid_users[username]        if user.id == id and checkpw(password.encode(),                       user.passphrase.encode()):            return user        else:            return {"message": "invalid user"}@app.get("/ch01/login/details/info")def login_info():        return {"message": "username and password are                             needed"}

This will give us anHTTP Status Code 422 (Unprocessable Entity) when accessinghttp://localhost:8080/ch01/login/details/info. There should be no problem accessing the URL, since the API service is almost a stub or trivial JSON data. What happenedin this scenario is that the fixed path’sdetails andinfo pathdirectories were treated asusername andpassword parameter values, respectively. Because of confusion, the built-in data validation of FastAPI will show us a JSON-formatted error message that says,{"detail":[{"loc":["query","id"],"msg":"field required","type":"value_error.missing"}]}. To fix this problem, all fixed paths should be declared first before the dynamic endpoint URLs with path parameters. Thus, the precedinglogin_info() service should be declared first beforelogin_with_token().

Query parameters

A query parameter is akey–value pair supplied after the end of an endpoint URL, indicated by aquestion mark (?). Just like the path parameter, this also holds therequest data. An API service can manage a series of query parameters separated by an ampersand (&). Like in path parameters, all query parameters are also declared in the service method. The followinglogin service is a perfect specimen that uses query parameters:

@app.get("/ch01/login/")def login(username: str,password: str):    if valid_users.get(username) == None:        return {"message": "user does not exist"}    else:        user = valid_users.get(username)        if checkpw(password.encode(),                user.passphrase.encode()):            return user        else:            return {"message": "invalid user"}

Thelogin service method usesusername andpassword as query parameters in thestr types. Both are required parameters, and assigning them withNone as parameter values will give a compiler error.

FastAPI supportsquery parameters that are complex types, such aslist anddict. Butthese Python collection types cannot specify the type of objects to store unless we apply thegeneric type hints for Python collections. The followingdelete_users() andupdate_profile_names() APIs use generic type hints,List andDict, in declaring query parameters that are container types with type checking and data validation:

from typing import Optional,List,Dict@app.delete("/ch01/login/remove/all")def delete_users(usernames: List[str]):    for user in usernames:        del valid_users[user]    return {"message": "deleted users"}@app.patch("/ch01/account/profile/update/names/{username}")def update_profile_names(username: str, id: UUID,                          new_names: Dict[str, str]):    if valid_users.get(username) == None:        return {"message": "user does not exist"}    elif new_names == None:        return {"message": "new names are required"}    else:        user = valid_users.get(username)        if user.id == id:            profile = valid_profiles[username]            profile.firstname = new_names['fname']            profile.lastname = new_names['lname']            profile.middle_initial = new_names['mi']            valid_profiles[username] = profile            return {"message": "successfully updated"}        else:            return {"message": "user does not exist"}

FastAPI alsoallows you to explicitly assign default values to servicefunction parameters.

Default parameters

There are times that weneed to specify default values to the query parameter(s) andpath parameter(s) of some API services to avoid validation error messages such asfield required andvalue_error.missing. Setting default values to parameters will allow the execution of an API method with or without supplying the parameter values. Depending on the requirement, assigned default values are usually0 for numeric types,False for bool types, empty string for string types, an empty list ([]) for List types, and an empty dictionary ({}) forDict types. The followingdelete pending users() andchange_password() services show us how to apply default values to the query parameter(s) and path parameter(s):

@app.delete("/ch01/delete/users/pending")def delete_pending_users(accounts: List[str] = []):    for user in accounts:        del pending_users[user]    return {"message": "deleted pending users"}@app.get("/ch01/login/password/change")def change_password(username: str,old_passw: str = '',                         new_passw: str = ''):    passwd_len = 8    if valid_users.get(username) == None:        return {"message": "user does not exist"}    elif old_passw == '' or new_passw == '':        characters = ascii_lowercase        temporary_passwd =              ''.join(random.choice(characters) for i in                      range(passwd_len))        user = valid_users.get(username)        user.password = temporary_passwd        user.passphrase =                   hashpw(temporary_passwd.encode(),gensalt())        return user    else:        user = valid_users.get(username)        if user.password == old_passw:            user.password = new_passw            user.passphrase = hashpw(new_pass.encode(),gensalt())            return user        else:            return {"message": "invalid user"}

delete_pending_users() can be executed even without passing any accounts argument, since accounts will bealways an emptyList by default. Likewise,change_password() canstill continue its process without passing anyold_passwd andnew_passw, since they are both always defaulted to emptystr.hashpw() is abcrypt utility function that generates a hashed passphrase from an autogeneratedsalt.

Optional parameters

If thepath and/orquery parameter(s) of a service is/are not necessarily needed to be supplied by theuser, meaning the API transactions can proceed with or withouttheir inclusion in the request transaction, then we set them asoptional. To declare an optional parameter, we need to import theOptional type from thetyping module and then use it to set the parameter. It should wrap the supposed data type of the parameter using brackets ([]) and can haveany default value if needed. Assigning theOptional parameter to aNone value indicates that its exclusion from the parameter passing is allowed by the service, but it will hold aNone value. The following services depict the use of optional parameters:

from typing importOptional, List, Dict@app.post("/ch01/login/username/unlock")def unlock_username(id:Optional[UUID] = None):    if id == None:        return {"message": "token needed"}    else:        for key, val in valid_users.items():            if val.id == id:                return {"username": val.username}        return {"message": "user does not exist"}@app.post("/ch01/login/password/unlock")def unlock_password(username: Optional[str] = None,                     id: Optional[UUID] = None):    if username == None:        return {"message": "username is required"}    elif valid_users.get(username) == None:        return {"message": "user does not exist"}    else:        if id == None:            return {"message": "token needed"}        else:            user = valid_users.get(username)            if user.id == id:                return {"password": user.password}            else:                return {"message": "invalid token"}

In theonline academic discussion forum application, we have services such as the precedingunlock_username() andunlock_password() services that declare all their parameters asoptional. Just do notforget to apply exception handling or defensivevalidation in your implementation when dealing with these kinds of parameters to avoidHTTP Status 500 (Internal Server Error).

Important note

The FastAPI framework does not allow you to directly assign theNone value to a parameter just to declare anoptional parameter. Although this is allowed with the old Python behavior, this is no longer recommended in the current Python versions for the purpose of built-in type checking and model validation.

Mixing all types of parameters

If you are planning toimplement an API service method that declares optional, required, and default query and path parameters altogether, you can pursue it because the framework supports it, but approach it with some caution due to some standards and rules:

@app.patch("/ch01/account/profile/update/names/{username}")def update_profile_names(id: UUID,username: str = '' ,            new_names: Optional[Dict[str, str]] = None):    if valid_users.get(username) == None:        return {"message": "user does not exist"}    elif new_names == None:        return {"message": "new names are required"}    else:        user = valid_users.get(username)        if user.id == id:            profile = valid_profiles[username]            profile.firstname = new_names['fname']            profile.lastname = new_names['lname']            profile.middle_initial = new_names['mi']            valid_profiles[username] = profile            return {"message": "successfully updated"}        else:            return {"message": "user does not exist"}

The updated version of the precedingupdate_profile_names() service declares ausername path parameter, aUUID id query parameter, and an optionalDict[str, str] type. With mixed parameter types, all required parameters should be declaredfirst, followed by default parameters, and last in the parameter list should be the optional types. Disregarding this ordering rule will generate acompiler error.

Request body

Arequest body is a bodyof data in bytes transmitted from a client to a serverthrough aPOST,PUT,DELETE, orPATCH HTTP method operation. In FastAPI, a service must declare a model object to represent and capture this request body to be processed for further results.

To implement a model class for therequest body, you should first import theBaseModel class from thepydantic module. Then, create a subclass of it to utilize all the properties and behavior needed by the path operation in capturing the request body. Here are some of the data models used by our application:

from pydantic importBaseModelclass User(BaseModel):    username: str    password: strclass UserProfile(BaseModel):    firstname: str    lastname: str    middle_initial: str    age: Optional[int] = 0    salary: Optional[int] = 0    birthday: date    user_type: UserType

The attributes of the model classes must be explicitly declared by applyingtype hints and utilizing the common and complex data types used in the parameter declaration. These attributes can also be set as required, default, and optional, just like in the parameters.

Moreover, thepydantic moduleallows the creation of nested models, even the deeplynested ones. A sample of these is shown here:

class ForumPost(BaseModel):    id: UUID    topic: Optional[str] = None    message: str    post_type: PostType    date_posted: datetime    username: strclass ForumDiscussion(BaseModel):    id: UUID    main_post: ForumPost    replies: Optional[List[ForumPost]] = None    author: UserProfile

As seen in the preceding code, we have aForumPost model, which has aPostType model attribute, andForumDiscussion, which has aList attribute ofForumPost, aForumPost model attribute, and aUserProfile attribute. This kind of modelblueprint is called anested model approach.

After creating these model classes, you can nowinject these objects into the services that are intendedto capture therequest body from the clients. The followingservices utilize ourUser andUserProfile model classes to manage the request body:

@app.post("/ch01/login/validate", response_model=ValidUser)def approve_user(user: User):    if not valid_users.get(user.username) == None:        returnValidUser(id=None, username = None,              password = None, passphrase = None)    else:        valid_user =ValidUser(id=uuid1(),              username= user.username,             password  = user.password,             passphrase = hashpw(user.password.encode(),                          gensalt()))        valid_users[user.username] = valid_user        del pending_users[user.username]        return valid_user@app.put("/ch01/account/profile/update/{username}")def update_profile(username: str,id: UUID,                    new_profile: UserProfile):    if valid_users.get(username) == None:        return {"message": "user does not exist"}    else:        user = valid_users.get(username)        if user.id == id:            valid_profiles[username] = new_profile            return {"message": "successfully updated"}        else:            return {"message": "user does not exist"}

Models can be declaredrequired, with adefault instance value, oroptional in the service method, dependingon the specification of the API. Missing or incorrect detailssuch asinvalid password orNone values in theapprove_user() service will emit theStatus Code 500 (Internal Server Error). How FastAPI handles exceptions will be part ofChapter 2,Exploring the Core Features, discussions.

Important note

There are two essential points we need to emphasize when dealing withBaseModel class types. First, thepydantic module has a built-in JSON encoder that converts the JSON-formatted request body to theBaseModel object. So, there is no need create a custom converter to map the request body to theBaseModel model. Second, to instantiate aBaseModel class, all its required attributes must be initialized immediately through the constructor’s named parameters.

Request headers

In a request-response transaction, itis not only the parameters that areaccessible by the REST API methods but also the information that describes the context of the client where the request originated. Some common request headers such asUser-Agent,Host,Accept,Accept-Language,Accept-Encoding,Referer, andConnection usually appear with request parameters and values during request transactions.

To access a request header, import first theHeader function from thefastapi module. Then, declare the variable that has the same name as the header in the method service asstr types and initialize the variable by calling theHeader(None) function. TheNone argument enables theHeader() function to declare the variable optionally, which is a best practice. For hyphenated request header names, the hyphen (-) should be converted to an underscore (_); otherwise, the Python compiler will flag a syntax error message. It is the task of theHeader() function to convert the underscore (_) to a hyphen (-) during request header processing.

Our online academic discussion forum application has averify_headers() servicethat retrieves core request headers needed to verify a client’s access to the application:

from fastapi importHeader@app.get("/ch01/headers/verify")def verify_headers(host: Optional[str] = Header(None),                    accept: Optional[str] = Header(None),                   accept_language:                       Optional[str] = Header(None),                   accept_encoding:                       Optional[str] = Header(None),                   user_agent:                        Optional[str] = Header(None)):    request_headers["Host"] = host    request_headers["Accept"] = accept    request_headers["Accept-Language"] = accept_language    request_headers["Accept-Encoding"] = accept_encoding    request_headers["User-Agent"] = user_agent    return request_headers

Important note

Non-inclusion of theHeader() function call in the declaration will let FastAPI treat the variables asquery parameters. Be cautious also with the spelling of the local parameter names, since theyare the request header names per se except for the underscore.

Response data

All API services in FastAPIshould returnJSON data, or it will be invalid and mayreturnNone by default. These responses can be formed usingdict,BaseModel, orJSONResponse objects. Discussions onJSONResponse will be discussed in the succeeding chapters.

Thepydantic module’s built-in JSON converter will manage the conversion of these custom responses to a JSON object, so there is no need to create a custom JSON encoder:

@app.post("/ch01/discussion/posts/add/{username}")def post_discussion(username: str, post: Post,                     post_type: PostType):    if valid_users.get(username) == None:        return{"message": "user does not exist"}    elif not (discussion_posts.get(id) == None):        return{"message": "post already exists"}    else:        forum_post = ForumPost(id=uuid1(),           topic=post.topic, message=post.message,           post_type=post_type,           date_posted=post.date_posted, username=username)        user = valid_profiles[username]        forum = ForumDiscussion(id=uuid1(),         main_post=forum_post, author=user, replies=list())        discussion_posts[forum.id] = forum        returnforum

The precedingpost_discussion() service returns two different hardcodeddict objects, withmessage as the key and an instantiatedForumDiscussion model.

On the other hand, this framework allows us to specify the return type of a service method. The settingof the return type happens in theresponse_model attributeof any of the@app path operations. Unfortunately, the parameter only recognizesBaseModel class types:

@app.post("/ch01/login/validate",response_model=ValidUser)def approve_user(user: User):        if not valid_users.get(user.username) == None:        returnValidUser(id=None, username = None,                    password = None, passphrase = None)    else:        valid_user = ValidUser(id=uuid1(),         username= user.username, password = user.password,          passphrase = hashpw(user.password.encode(),                 gensalt()))        valid_users[user.username] = valid_user        del pending_users[user.username]        returnvalid_user

The precedingapprove_user() service specifies the required return of the API method, which isValidUser.

Now, let us explore how FastAPI handles form parameters.

Handling form parameters

When API methods are designed to handle web forms, the services involved are required toretrieve form parameters instead of the request body because this form data is normally encoded as anapplication/x-www-form-urlencoded media type. These form parameters are conventionallystring types, but thepydantic module’s JSON encoder can convert each parameter value to its respective valid type.

All the form parameter variables can be declaredrequired, withdefault values, oroptional using the same set of Python types we used previously. Then, thefastapi module has aForm function that needs to be imported to initialize these form parameter variables during their declaration. To set these form parameters asrequired, theForm() function must have the ellipses () argument, thus calling it asForm(…):

from fastapi import FastAPI,Form@app.post("/ch01/account/profile/add",                        response_model=UserProfile)def add_profile(uname: str,                 fname: str = Form(...),                 lname: str = Form(...),                mid_init: str = Form(...),                user_age: int = Form(...),                sal: float = Form(...),                bday: str = Form(...),                utype: UserType = Form(...)):    if valid_users.get(uname) == None:        return UserProfile(firstname=None, lastname=None,               middle_initial=None, age=None,               birthday=None, salary=None, user_type=None)    else:        profile = UserProfile(firstname=fname,              lastname=lname, middle_initial=mid_init,              age=user_age, birthday=datetime.strptime(bday,                '%m/%d/%Y'), salary=sal, user_type=utype)        valid_profiles[uname] = profile        return profile

The precedingadd_profile() service shows us how to call theForm(…) function to return aForm object during the parameter declaration.

Important note

Form-handling services will not work if thepython-multipart module is not installed.

Sometimes, we needbrowser cookies to establish an identity for our application, leave trails in the browser for every user transaction, or store product information for a purpose. If FastAPI can manage form data, it can also do the same with cookies.

Managing cookies

Acookie is a piece ofinformation stored in the browser to pursue some purpose, suchas login user authorization, web agent responsegeneration, and session handling-related tasks. One cookie is always a key-value pair that are both string types.

FastAPI allows services to create cookies individually through theResponse library class from itsfastapi module. To use it, it needs to appear as the first local parameter of the service, but we do not let the application or client pass an argument to it. Using the dependency injection principle, the framework will provide theResponse instance to the service and not the application. When the service has other parameters to declare, the additional declaration should happen right after the declaration of theResponse parameter.

TheResponse object has aset_cookie() method that contains two required named parameters: thekey, which sets the cookie name, and thevalue, which stores the cookie value. This method only generates one cookie and stores it in the browser afterward:

@app.post("/ch01/login/rememberme/create/")def create_cookies(resp: Response, id: UUID,                    username: str = ''):    resp.set_cookie(key="userkey", value=username)    resp.set_cookie(key="identity", value=str(id))    return {"message": "remember-me tokens created"}

The precedingcreate_cookies() method shows us the creation ofremember-me tokens such asuserkey andidentity for theremember-me authorization of ouronline academic discussion forum project.

To retrieve these cookies, local parameters that have the same name as the cookies are declared in theservice method asstr types, since cookie values arealways strings. As withHeader andForm, thefastapi module also provides aCookie function that is needed to initialize each declared cookie parameter variable. TheCookie() function should always have theNone argument to set the parameters optionally, ensuring that the API method executes without problems whenever the headers are not present in the request transaction. The followingaccess_cookie() service retrieves all theremember-me authorization cookies created by the previous service:

@app.get("/ch01/login/cookies")def access_cookie(userkey: Optional[str] = Cookie(None),            identity: Optional[str] = Cookie(None)):    cookies["userkey"] = userkey    cookies["identity"] = identity    return cookies

Summary

This chapter is essential to familiarize ourselves with FastAPI and understand its basic components. The concept that we can get from this chapter can measure how much adjustment and effort we need to invest into translating or rewriting some existing applications to FastAPI. Knowing its basics will help us learn how to install its modules, structure the project directories, and learn the core library classes and functions needed to build a simple enterprise-grade application.

With the help of our recipeonline academic discussion forum application, this chapter showed us how to build different REST APIs associated with HTTP methods using the FastAPI module class and Pythondef functions. From there, we learned how to capture incoming request data and headers using the local parameters of the API methods and how these API methods should return a response to the client. And through this chapter, we saw how easy it is for FastAPI to capture form data from<form></form> of any UI templates and that is using theForm function. Aside from theForm function, the FastAPI module also has theCookie function to help us create and retrieve cookies from the browser, andHeader to retrieve the request header part of an incoming request transaction.

Overall, this chapter has prepared us for advanced discussions that will center on other features of FastAPI that can help us upgrade our simple applications to full-blown ones. The next chapter will cover these essential core features, which will provide our application with the needed response encoder and generator, exception handlers, middleware, and other components related to asynchronous transactions.

Left arrow icon

Page1 of 9

Right arrow icon
Download code iconDownload Code

Key benefits

  • Provides a reference that contains definitions, illustrations, comparative analysis, and the implementation of real-world apps
  • Covers concepts, core details, and advanced integration and design-related topics
  • Imparts context, app templates, suggestions, and insights that are helpful to actual projects

Description

FastAPI is an Asynchronous Server Gateway Interface (ASGI)-based framework that can help build modern, manageable, and fast microservices. Because of its asynchronous core platform, this ASGI-based framework provides the best option when it comes to performance, reliability, and scalability over the WSGI-based Django and Flask. When working with Python, Flask, and Django microservices, you’ll be able to put your knowledge to work with this practical guide to building seamlessly manageable and fast microservices.You’ll begin by understanding the background of FastAPI and learning how to install, configure, and use FastAPI to decompose business units. You’ll explore a unique and asynchronous REST API framework that can provide a better option when it comes to building microservices. After that, this book will guide you on how to apply and translate microservices design patterns in building various microservices applications and RESTful APIs using the FastAPI framework.By the end of this microservices book, you’ll be able to understand, build, deploy, test, and experiment with microservices and their components using the FastAPI framework.

Who is this book for?

This book is for Python web developers, advanced Python developers, and backend developers using Flask or Django who want to learn how to use the FastAPI framework to implement microservices. Readers familiar with the REST API and microservices will also benefit from this book. Some parts of the book contain general concepts, processes, and instructions that intermediate-level developers and Python enthusiasts can relate to as well.

What you will learn

  • Understand, orient, and implement REST APIs using the basic components of the FastAPI framework
  • Build asynchronous as well as synchronous REST services using the built-in pydantic module and asyncio support
  • Create small-scale and large-scale microservices applications using features supported by FastAPI
  • Build event-driven and message-driven applications using the framework
  • Create an asynchronous and synchronous data layer with both relational and NoSQL databases
  • Perform numerical and symbolic computations with FastAPI

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date :Aug 30, 2022
Length:420 pages
Edition :1st
Language :English
ISBN-13 :9781803238791
Languages :
Concepts :
Tools :

What do you get with eBook?

Product feature iconInstant access to your Digital eBook purchase
Product feature icon Download this book inEPUB andPDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature iconDRM FREE - Read whenever, wherever and however you want
Product feature iconAI Assistant (beta) to help accelerate your learning
OR

Contact Details

Modal Close icon
Payment Processing...
tickCompleted

Billing Address

Product Details

Publication date :Aug 30, 2022
Length:420 pages
Edition :1st
Language :English
ISBN-13 :9781803238791
Category :
Languages :
Concepts :
Tools :

Packt Subscriptions

See our plans and pricing
Modal Close icon
$19.99billed monthly
Feature tick iconUnlimited access to Packt's library of 7,000+ practical books and videos
Feature tick iconConstantly refreshed with 50+ new titles a month
Feature tick iconExclusive Early access to books as they're written
Feature tick iconSolve problems while you work with advanced search and reference features
Feature tick iconOffline reading on the mobile app
Feature tick iconSimple pricing, no contract
$199.99billed annually
Feature tick iconUnlimited access to Packt's library of 7,000+ practical books and videos
Feature tick iconConstantly refreshed with 50+ new titles a month
Feature tick iconExclusive Early access to books as they're written
Feature tick iconSolve problems while you work with advanced search and reference features
Feature tick iconOffline reading on the mobile app
Feature tick iconChoose a DRM-free eBook or Video every month to keep
Feature tick iconPLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick iconExclusive print discounts
$279.99billed in 18 months
Feature tick iconUnlimited access to Packt's library of 7,000+ practical books and videos
Feature tick iconConstantly refreshed with 50+ new titles a month
Feature tick iconExclusive Early access to books as they're written
Feature tick iconSolve problems while you work with advanced search and reference features
Feature tick iconOffline reading on the mobile app
Feature tick iconChoose a DRM-free eBook or Video every month to keep
Feature tick iconPLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick iconExclusive print discounts

Frequently bought together


Building Python Web APIs with FastAPI
Building Python Web APIs with FastAPI
Read more
Jul 2022216 pages
Full star icon4.7 (9)
eBook
eBook
$29.99$33.99
$41.99
Mastering Python 2E
Mastering Python 2E
Read more
May 2022710 pages
Full star icon4.6 (65)
eBook
eBook
$25.99$28.99
$49.99
Building Python Microservices with FastAPI
Building Python Microservices with FastAPI
Read more
Aug 2022420 pages
Full star icon3.9 (9)
eBook
eBook
$33.99$37.99
$46.99
Stars icon
Total$138.97
Building Python Web APIs with FastAPI
$41.99
Mastering Python 2E
$49.99
Building Python Microservices with FastAPI
$46.99
Total$138.97Stars icon

Table of Contents

16 Chapters
Part 1: Application-Related Architectural Concepts for FastAPI microservice developmentChevron down iconChevron up icon
Part 1: Application-Related Architectural Concepts for FastAPI microservice development
Chapter 1: Setting Up FastAPI for StartersChevron down iconChevron up icon
Chapter 1: Setting Up FastAPI for Starters
Technical requirements
Setting up the development environment
Initializing and configuring FastAPI
Designing and implementing REST APIs
Managing user requests and server response
Handling form parameters
Managing cookies
Summary
Chapter 2: Exploring the Core FeaturesChevron down iconChevron up icon
Chapter 2: Exploring the Core Features
Technical requirements
Structuring and organizing huge projects
Managing API-related exceptions
Converting objects to JSON-compatible types
Managing API responses
Creating background processes
Using asynchronous path operations
Applying middleware to filter path operations
Summary
Chapter 3: Investigating Dependency InjectionChevron down iconChevron up icon
Chapter 3: Investigating Dependency Injection
Technical requirements
Applying IoC/DI
Exploring ways of injecting dependencies
Organizing a project based on dependencies
Using third-party containers
Scoping of dependables
Summary
Chapter 4: Building the Microservice ApplicationChevron down iconChevron up icon
Chapter 4: Building the Microservice Application
Technical requirements
Applying the decomposition pattern
Mounting the submodules
Creating a common gateway
Implementing the main endpoint
Evaluating the microservice ID
Applying the exception handlers
Centralizing the logging mechanism
Building the logging middleware
Using the httpx module
Using the requests module
Applying the domain modeling approach
Creating the layers
Identifying the domain models
Building the repository and service layers
Managing a microservice’s configuration details
Summary
Part 2: Data-Centric and Communication-Focused Microservices Concerns and IssuesChevron down iconChevron up icon
Part 2: Data-Centric and Communication-Focused Microservices Concerns and Issues
Chapter 5: Connecting to a Relational DatabaseChevron down iconChevron up icon
Chapter 5: Connecting to a Relational Database
Technical requirements
Preparing for database connectivity
Creating CRUD transactions using SQLAlchemy
Implementing async CRUD transactions using SQLAlchemy
Using GINO for async transactions
Using Pony ORM for the repository layer
Building the repository using Peewee
Applying the CQRS design pattern
Summary
Chapter 6: Using a Non-Relational DatabaseChevron down iconChevron up icon
Chapter 6: Using a Non-Relational Database
Technical requirements
Setting up the database environment
Applying the PyMongo driver for synchronous connections
Creating async CRUD transactions using Motor
Implementing CRUD transactions using MongoEngine
Implementing async transactions using Beanie
Building async repository for FastAPI using ODMantic
Creating CRUD transactions using MongoFrames
Summary
Chapter 7: Securing the REST APIsChevron down iconChevron up icon
Chapter 7: Securing the REST APIs
Technical requirements
Implementing Basic and Digest authentication
Implementing password-based authentication
Applying JWTs
Creating scope-based authorization
Building the authorization code flow
Applying the OpenID Connect specification
Using built-in middlewares for authentication
Summary
Chapter 8: Creating Coroutines, Events, and Message-Driven TransactionsChevron down iconChevron up icon
Chapter 8: Creating Coroutines, Events, and Message-Driven Transactions
Technical requirements
Implementing coroutines
Creating asynchronous background tasks
Understanding Celery tasks
Building message-driven transactions using RabbitMQ
Building publish/subscribe messaging using Kafka
Implementing asynchronous Server-Sent Events (SSE)
Building an asynchronous WebSocket
Applying reactive programming in tasks
Customizing events
Summary
Part 3: Infrastructure-Related Issues, Numerical and Symbolic Computations, and Testing MicroservicesChevron down iconChevron up icon
Part 3: Infrastructure-Related Issues, Numerical and Symbolic Computations, and Testing Microservices
Chapter 9: Utilizing Other Advanced FeaturesChevron down iconChevron up icon
Chapter 9: Utilizing Other Advanced Features
Technical requirements
Applying session management
Managing the CORS mechanism
Customizing APIRoute and Request
Choosing the appropriate responses
Applying the OpenAPI 3.x specification
Testing the API endpoints
Summary
Chapter 10: Solving Numerical, Symbolic, and Graphical ProblemsChevron down iconChevron up icon
Chapter 10: Solving Numerical, Symbolic, and Graphical Problems
Technical requirements
Setting up the projects
Implementing symbolic computations
Creating arrays and DataFrames
Performing statistical analysis
Generating CSV and XLSX reports
Plotting data models
Simulating a BPMN workflow
Using GraphQL queries and mutations
Utilizing the Neo4j graph database
Summary
Chapter 11: Adding Other Microservice FeaturesChevron down iconChevron up icon
Chapter 11: Adding Other Microservice Features
Technical requirements
Setting up the virtual environment
Checking the API properties
Implementing open tracing mechanisms
Setting up service registry and client-side service discovery
Deploying and running applications using Docker
Using Docker Compose for deployment
Using NGINX as an API Gateway
Integrating Flask and Django sub-applications
Summary
IndexChevron down iconChevron up icon
Index
Why subscribe?
Other Books You May EnjoyChevron down iconChevron up icon
Other Books You May Enjoy
Packt is searching for authors like you
Share your thoughts

Recommendations for you

Left arrow icon
Full-Stack Flask and React
Full-Stack Flask and React
Read more
Oct 2023408 pages
Full star icon3.8 (5)
eBook
eBook
$27.99$31.99
$39.99
Real-World Web Development with .NET 9
Real-World Web Development with .NET 9
Read more
Dec 2024578 pages
Full star icon3.5 (4)
eBook
eBook
$35.98$39.99
$49.99
Django 5 By Example
Django 5 By Example
Read more
Apr 2024820 pages
Full star icon4.6 (40)
eBook
eBook
$35.98$39.99
$49.99
React and React Native
React and React Native
Read more
Apr 2024518 pages
Full star icon4.3 (10)
eBook
eBook
$31.99$35.99
$43.99
Scalable Application Development with NestJS
Scalable Application Development with NestJS
Read more
Jan 2025612 pages
Full star icon4.5 (6)
eBook
eBook
$27.99$31.99
$39.99
Responsive Web Design with HTML5 and CSS
Responsive Web Design with HTML5 and CSS
Read more
Sep 2022504 pages
Full star icon4.5 (57)
eBook
eBook
$31.99$35.99
$44.99
$49.99
Modern Full-Stack React Projects
Modern Full-Stack React Projects
Read more
Jun 2024506 pages
Full star icon4.8 (9)
eBook
eBook
$31.99$35.99
$44.99
Learning Angular
Learning Angular
Read more
Jan 2025486 pages
Full star icon4 (6)
eBook
eBook
$29.99$33.99
$41.99
Right arrow icon

Customer reviews

Top Reviews
Rating distribution
Full star iconFull star iconFull star iconHalf star iconEmpty star icon3.9
(9 Ratings)
5 star55.6%
4 star0%
3 star33.3%
2 star0%
1 star11.1%
Filter icon Filter
Top Reviews

Filter reviews by




Moses KayandaSep 11, 2022
Full star iconFull star iconFull star iconFull star iconFull star icon5
I got an opportunity to go through the book as I was learning about FastAPI framework and I must say the author has done very well explaining what I thought was a complex domain. Going through the book opens up your understanding of creating an enterprise grade microservice application. You will a very detailed introduction into setting up FastAPI endpoints, get a feel of working with decorators (which prior to this, my knowledge was shacky), to core features how to connect a relational database, securing REST APIs to utilizing and adding advanced features such as OpenTracing, client-side service discovery and likes, among other essential topic areas. You will learn how to manage exceptions for building resilient microservice architecture when business processes become intricate. The book also touches on dependency injection and how it affects our FastAPIs projects.The book acts as a detailed reference guide whether you are learning this or implementing the same in your day job. By the end of it, you should have familiarized yourself with all the core components of FastAPI helping you upgrade the simple applications to quality ones.The book has left a curiosity in me to further learn about microservice architecture. I would highly recommend this book to anyone who would live to delve knees deep into this domain area.
Amazon Verified reviewAmazon
THOMAS GEORGE THOMASSep 17, 2022
Full star iconFull star iconFull star iconFull star iconFull star icon5
This book is well written and is in an easy-to-understand manner. I am new to FastAPI and I got a good sense of it going through this book. I especially liked the chapters on how to connect FastAPI with SQL and NoSQL databases. A lot of the examples in this book are based on real-life scenarios which helped me think about designing systems efficiently. It also talks about how to leverage microservices to work with Kafka, Neo4j, and GraphQL platforms and also how to deploy and run on docker.Overall, it's a great book with lots of real-world applications. I would recommend it to someone looking for good microservices solutions design.
Amazon Verified reviewAmazon
Jose MachadoJun 11, 2023
Full star iconFull star iconFull star iconFull star iconFull star icon5
The book kicks off with a stellar opening chapter that briefly summarizes the key concepts of FastAPI. This explanation is designed to welcome newcomers into the realm of FastAPI, while also providing an engaging refresher for those already familiar with the framework. The second chapter delves deeper into the core features of the framework, paving the way for the rest of the book.Is amazing to see how these interconnected subjects have been transformed by the author into self-contained sections that can be read and understood in isolation, offering the reader the flexibility to navigate the book nonlinearly. Once the first two chapters are assimilated, you have the freedom to choose your subsequent learning path.This book is a powerful resource for anyone aspiring to become a proficient and comprehensive FastAPI Python developer. It equips you for a myriad of topics that extend beyond merely utilizing the library, such as multi-layered dependency injection, microservice design principles, interacting with non-relational databases (which are frequently utilized in contemporary projects), addressing security concerns, and various other topics.In spite of its compelling content, I couldn't ignore the errors present in some of the annotations and the less-than-ideal formatting of the code. Nonetheless, this is a commendable book for programmers who prioritize efficiency, code quality, and adherence to best practices. However, note that novice programmers might find it challenging to progress past the second chapter. Some of the advanced topics might not appeal to beginners in the early stages of their coding journey, who are often more focused on getting tasks accomplished rather than delving into intricate details.
Amazon Verified reviewAmazon
SamyakJan 03, 2023
Full star iconFull star iconFull star iconFull star iconFull star icon5
Easy to understand the concept and to implement the Rest API using FastAPI framework.the book contains definitions, Examples and comparative analysis and the implementation of real world apps. Definitely recommend.
Amazon Verified reviewAmazon
RUI WANGSep 30, 2022
Full star iconFull star iconFull star iconFull star iconFull star icon5
This book has been a big help to me. I've been trying to learn Python myself and this book is a great guide. What I love the most is that it is so structured and organized that after teaching the concepts, it also has practice chapters where I could apply what I learned. It is always hard to keep going without actual practice because you thought you learned but you didn't. For every new concept the author attached code examples and detailed word explanations, which is super helpful. Strongly recommend!
Amazon Verified reviewAmazon
  • Arrow left icon Previous
  • 1
  • 2
  • Arrow right icon Next

People who bought this also bought

Left arrow icon
Responsive Web Design with HTML5 and CSS
Responsive Web Design with HTML5 and CSS
Read more
Sep 2022504 pages
Full star icon4.5 (57)
eBook
eBook
$31.99$35.99
$44.99
$49.99
React and React Native
React and React Native
Read more
May 2022606 pages
Full star icon4.6 (17)
eBook
eBook
$35.98$39.99
$49.99
Right arrow icon

About the author

Profile icon Sherwin John C. Tragura
Sherwin John C. Tragura
LinkedIn iconGithub icon
Sherwin John C. Tragura is currently a subject matter expert and technical consultant in a company in the Philippines. He has been part of many development teams customizing Alfresco DMS/RMS and building Java and Python standalone and web projects. He is also a certified professional and bootcamp technical trainer who has delivered technical training on Java, Jakarta EE, C#, .NET, Python, Node frameworks, and other customized training courses since 2011. He was also associated as a lecturer with the Dela Salle University-Manila, Colegio de San Juan de Letran-Calamba, and the University of the Philippines-Los Banos. He is the author of other Packt books, including Spring MVC Blueprints, Spring 5 Cookbook, and Building Python Microservices with FastAPI.
Read more
See other products by Sherwin John C. Tragura
Getfree access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

How do I buy and download an eBook?Chevron down iconChevron up icon

Where there is an eBook version of a title available, you can buy it from the book details for that title. Add either the standalone eBook or the eBook and print book bundle to your shopping cart. Your eBook will show in your cart as a product on its own. After completing checkout and payment in the normal way, you will receive your receipt on the screen containing a link to a personalised PDF download file. This link will remain active for 30 days. You can download backup copies of the file by logging in to your account at any time.

If you already have Adobe reader installed, then clicking on the link will download and open the PDF file directly. If you don't, then save the PDF file on your machine and download the Reader to view it.

Please Note: Packt eBooks are non-returnable and non-refundable.

Packt eBook and Licensing When you buy an eBook from Packt Publishing, completing your purchase means you accept the terms of our licence agreement. Please read the full text of the agreement. In it we have tried to balance the need for the ebook to be usable for you the reader with our needs to protect the rights of us as Publishers and of our authors. In summary, the agreement says:

  • You may make copies of your eBook for your own use onto any machine
  • You may not pass copies of the eBook on to anyone else
How can I make a purchase on your website?Chevron down iconChevron up icon

If you want to purchase a video course, eBook or Bundle (Print+eBook) please follow below steps:

  1. Register on our website using your email address and the password.
  2. Search for the title by name or ISBN using the search option.
  3. Select the title you want to purchase.
  4. Choose the format you wish to purchase the title in; if you order the Print Book, you get a free eBook copy of the same title. 
  5. Proceed with the checkout process (payment to be made using Credit Card, Debit Cart, or PayPal)
Where can I access support around an eBook?Chevron down iconChevron up icon
  • If you experience a problem with using or installing Adobe Reader, the contact Adobe directly.
  • To view the errata for the book, see www.packtpub.com/support and view the pages for the title you have.
  • To view your account details or to download a new copy of the book go to www.packtpub.com/account
  • To contact us directly if a problem is not resolved, use www.packtpub.com/contact-us
What eBook formats do Packt support?Chevron down iconChevron up icon

Our eBooks are currently available in a variety of formats such as PDF and ePubs. In the future, this may well change with trends and development in technology, but please note that our PDFs are not Adobe eBook Reader format, which has greater restrictions on security.

You will need to use Adobe Reader v9 or later in order to read Packt's PDF eBooks.

What are the benefits of eBooks?Chevron down iconChevron up icon
  • You can get the information you need immediately
  • You can easily take them with you on a laptop
  • You can download them an unlimited number of times
  • You can print them out
  • They are copy-paste enabled
  • They are searchable
  • There is no password protection
  • They are lower price than print
  • They save resources and space
What is an eBook?Chevron down iconChevron up icon

Packt eBooks are a complete electronic version of the print edition, available in PDF and ePub formats. Every piece of content down to the page numbering is the same. Because we save the costs of printing and shipping the book to you, we are able to offer eBooks at a lower cost than print editions.

When you have purchased an eBook, simply login to your account and click on the link in Your Download Area. We recommend you saving the file to your hard drive before opening it.

For optimal viewing of our eBooks, we recommend you download and install the free Adobe Reader version 9.


[8]ページ先頭

©2009-2025 Movatter.jp