Practical Rust Web Projects: Building Cloud and Web-Based Applications Shing Lyu all chapter instant download
Practical Rust Web Projects: Building Cloud and Web-Based Applications Shing Lyu all chapter instant download
com
https://textbookfull.com/product/practical-rust-web-
projects-building-cloud-and-web-based-applications-shing-
lyu/
OR CLICK BUTTON
DOWNLOAD NOW
https://textbookfull.com/product/building-web-and-mobile-arcgis-
server-applications-with-javascript-lewin/
textboxfull.com
https://textbookfull.com/product/practical-node-js-building-real-
world-scalable-web-apps-azat-mardan/
textboxfull.com
https://textbookfull.com/product/programming-c-8-0-build-cloud-web-
and-desktop-applications-ian-griffiths/
textboxfull.com
https://textbookfull.com/product/blazor-revealed-building-web-
applications-in-net-1st-edition-peter-himschoot/
textboxfull.com
https://textbookfull.com/product/angular-5-projects-learn-to-build-
single-page-web-applications-using-70-projects-1st-edition-mark-clow/
textboxfull.com
https://textbookfull.com/product/web-performance-in-action-building-
faster-web-pages-1st-edition-jeremy-wagner/
textboxfull.com
https://textbookfull.com/product/flask-web-development-developing-web-
applications-with-python-2nd-edition-miguel-grinberg/
textboxfull.com
Shing Lyu
The publisher, the authors and the editors are safe to assume that the
advice and information in this book are believed to be true and accurate
at the date of publication. Neither the publisher nor the authors or the
editors give a warranty, expressed or implied, with respect to the
material contained herein or for any errors or omissions that may have
been made. The publisher remains neutral with regard to jurisdictional
claims in published maps and institutional affiliations.
If you are reading this book, you are probably as excited about Rust as I
am. Since the first stable release in 2015, Rust has come a long way in
terms of features and stability. Developers around the world are
fascinated about how Rust can combine features that were once
thought of as unavoidable trade-offs: performance with memory safety,
low-level control with productivity. Despite its infamous steep learning
curve, Rust has gained popularity over the years. It was named the
“most loved programming language” in a StackOverflow survey four
years in a row, from 2016 to 2020. Many big companies and
organizations—like Facebook, Microsoft, Dropbox, and npm—have
started using Rust in production.
How are people using Rust? If we take a look at crates.io, the official
Rust crates (libraries) registry, there are over 28,900 crates and over a
billion downloads. There are 47 categories on crates.io,1 ranging from
the command-line interfaces, cryptography, databases, games,
operating systems, and many more. But one of the most exciting fields
is web programming. Many people spend most of their waking time
online. There are roughly 1.5 billion websites on the World Wide Web.
So it’s natural that Rusticians are looking for ways to build websites and
web applications with Rust.
This book focuses on Rust for web applications. Since the backend is
usually more language-agnostic, most of the chapters will be about the
backend. We’ll follow the history of how the backend evolves, starting
with server-side-rendered websites. Then we’ll develop REST APIs and
WebSocket servers. Finally, we’ll deploy this API onto the cloud using
serverless technologies. That doesn’t mean Rust can’t be used in the
frontend. With WebAssembly now available in most mainstream
browsers, we can compile our Rust code to WebAssembly and run it in
browsers. This unlocks a lot of potential for highly-performant
applications in the frontend. After reading this book, you should have a
good grasp of how to build a full-stack application in Rust.
Who Is This Book For?
This book will be useful for:
People who already know basic Rust syntax, but want to learn how to
build web applications in Rust.
People who are considering using Rust to build production-ready
systems.
People who have experience in web development and want to see
how Rust can fit in.
If you already know how to code Rust, this book will help you learn
web development in Rust. You have probably built a few command-line
games and tools while reading The Rust Book2 or other introductory
courses. The final project in The Rust Book teaches you to build a toy
web server. But how do you build production-ready web services? This
book will introduce you to web frameworks and crates in order to apply
your Rust skill on the web. If you already know web development in
other languages (e.g., Node.js, Java, Go, Python, Ruby, etc.), this book
will help you see how Rust makes it more secure and ergonomic to
building web applications.
Who Is This Book Not For?
This book might not be that useful for:
People who want to learn the Rust programming language itself.
People who want to learn the fundamentals of web development.
This book is not a course on the Rust programming language itself,
nor is it trying to teach Rust’s syntax via examples. We’ll focus on how
to apply Rust to web applications, assuming you already know Rust’s
syntax and its language features. There are many excellent books on
Rust, like The Rust Programming Language by Steve Klabnik and Carol
Nichols. You can also find online books, interactive tutorials, and videos
on the Learn Rust section of the official website.3 I try to explain the
fundamental web development concepts before implementing them.
But this book does not focus on teaching general web development
concepts through Rust, so the explanations will be brief. You’ll get more
out of this book if you already have some experience with web
development in other languages.
Pure-Rust
I try to find libraries that are built purely in Rust. Rust’s FFI (foreign
function interface) allows you to call existing C libraries (and many
other languages) from Rust. Therefore, the easiest way to build Rust
applications quickly is to leverage existing libraries in other languages.
These libraries are usually designed with other languages in mind, so
wrapping them in Rust results in a weird and not idiomatic Rust API. So
if there are pure Rust libraries, I tend to choose those.
Maturity
However, not every pure Rust library is mature. Because many Rust
libraries are built from a clean slate, the developers tried to experiment
with the latest technology, but that might mean that the architecture
and API design is very fragile and changes frequently. Some of the
libraries showed great potential in their early days, but then the
development slowed down, and the projects eventually went into
maintenance mode or were even abandoned. We aim to build useful
software rather than experiment with exciting technologies and then
throw the code away. Therefore, we need to be pragmatic and choose a
library that is mature enough and uses widely-accepted design
patterns.
Popularity
If two or more candidates meet the previous criteria, I choose the most
popular one. Popularity is based on a combination of factors, including:
Number of downloads on crates.io
Pace of development and release
Discussions on issue trackers and discussion forums
Media coverage
Although popularity is not a guarantee of success, a popular project
is more likely to have a big enough community that supports it and
keeps it alive. This can help us find a library that has the most potential
to stick around longer in the future. You are also more likely to get
support and answers online.
For backend-heavy chapters, I try to use plain JavaScript, HTML, and
CSS, without additional frameworks like React.js, jQuery, or SCSS. This
helps to keep the focus on the backend and avoid the need to learn a
new framework that might be out of fashion soon.
Chapter Overview
In Chapter 2, I started with the traditional form of website architecture:
server-side rendered websites. You’ll learn how to use the actix-web
framework to set up a web server. Then, you’ll learn how to render
dynamic HTML pages using a template engine. To make the website
even more interactive, you’ll set up a database and render the website
using the data in that database. Finally, you’ll learn how to build a page
that adds new information to the database.
In Chapter 3, you’ll learn about a different website architecture that
is popular among modern websites: using JavaScript to render dynamic
data provided by a REST API. You’ll learn how to return JSON-formatted
data from the API. I also introduce other commonly used techniques
that didn’t fit into the previous chapter: input validation, error
handling, logging, and enabling HTTPS.
In Chapter 4, you’ll learn about a different protocol, WebSocket, that
can help you build real-time, bidirectional communication. I’ll show you
how to use WebSocket to push real-time notifications to the client.
Then you’ll build a full-duplex chat application.
In Chapter 5, you’ll learn how to build a REST API using AWS
Lambda and other serverless services. You’ll learn how to use the AWS
SDK to communicate with the DynamoDB database. You’ll also learn
how to deploy the frontend to AWS S3 and connect it to the REST API.
After finishing this chapter, you’ll have a fully-functional website on the
Internet without worrying about server maintenance.
In Chapter 6, I change the focus to the frontend. First, you’ll learn
how to compile your Rust code to WebAssembly (Wasm) so it can run
in browsers. You’ll build a JavaScript-Wasm hybrid image-processing
application in the browser so you can leverage Wasm’s high
performance. Then you’ll learn how to use a frontend framework to
build the whole frontend application using only Rust.
Source Code
All the source code for this book is available on GitHub at
https://github.com/apress/practical-rust-web-
projects. The source code is also accessible via the Download Source
Code button located at
https://www.apress.com/us/book/9781484265888.
When I include source code in the book, I only include the part that
is relevant to the point being discussed. The irrelevant parts are
omitted with comments like this:
// ...
Footnotes
1 https://crates.io/categories
2 https://doc.rust-lang.org/book/
3 https://www.rust-lang.org/learn
© Shing Lyu 2021
S. Lyu, Practical Rust Web Projects
https://doi.org/10.1007/978-1-4842-6589-5_2
2. Developing Websites
Shing Lyu1
(1) Amsterdam, The Netherlands
There is no denying that the web is one of the most popular platforms on
Earth now. There are over 1.7 billion websites on the World Wide Web. And if
you look at job boards for developers, web developers take up a large
proportion of it. There are already many established programming languages
for building the backend: Java, PHP, Python, Ruby, Node.js, and Go, just to
name a few. But Rust fits perfectly into the web domain because of a few
reasons:
Security
Concurrency
Low-level control
Web security has been a big headache for everyone involved in building
websites. But many vulnerabilities are due to bugs that can be caught by
Rust’s type checker and borrow checker. By having Rust check your code at
compile-time, you can prevent many runtime vulnerabilities that might go
undetected and be exploited when you least expect them to.
Nowadays, popular websites need to handle a large number of concurrent
users. Therefore, concurrency and efficiency are crucial for web server
software to handle more and more users. Rust’s focus on ”fearless
concurrency” makes it easier to handle a large number of concurrent
requests. The relatively new async/await syntax also makes async I/O
more accessible to the average Rust programmer. On top of thread safety and
async I/O, Rust’s ability to control low-level CPU and memory opens up the
possibility of squeezing more performance out of the server hardware.
Rust also has a vibrant ecosystem that provides both high-level
frameworks and low-level control over networking, database access, and
type-safe templating. We are going to explore how to build a server-side
rendered website in Rust.
What Are You Building?
In the game Pokémon, there is a device called Pokédex, which is an
index/encyclopedia of all Pokémons. In this chapter, we are going to build a
cat index called Catdex. The Catdex should have the following features:
Show a list of cats. This demonstrates how to render a list of things using a
server-side template.
Read the cats from a database. This demonstrates how to set up a database
with Object Relational Mapping (ORM).
Use a form to add a new cat to the database. This demonstrates how to send
POST requests and insert the data into a database.
Show a specific detail page for each cat. This demonstrates how to read
parameters from the URL path.
There are many ways to architect a website. One important distinction is
server-side rendering versus client-side rendering. In server-side rendering,
the HTML is generated on the server-side when a request comes in. In client-
side rendering, the page is mostly generated in the browser by client-side
frameworks like React, Vue, or Angular. The client-side framework then makes
an HTTP request to a backend API to retrieve data that should go on the page.
We’ll talk about RESTful APIs in Chapter 3 and client-side rendering in
Chapter 6. But in this chapter, we’ll focus on server-side rendering.
We’ll be using the actix-web framework as our web framework.
actix-web doesn’t dictate which template engine and database you should
use. We’ll be choosing the Handlebar for templating. For the database, we’ll be
using a PostgreSQL database through the Diesel ORM and r2d2 connection
pool.
Hello World!
To start an Actix application, you first need to create an empty project with
cargo, then add actix-web as dependencies. Run the following command
in your terminal:
Once cargo adds the dependencies, your Cargo.toml should look like
Listing 2-1.
[package]
name = "hello-world"
# ...
[dependencies]
actix-web = "3"
Listing 2-1 Cargo.toml for a Hello World Actix Application
Now, open the src/main.rs file and copy Listing 2-2 into it.
#[actix_web::main]
async fn main() -> std::io::Result<()> {
println!("Listening on port 8080");
HttpServer::new(|| {
App::new().route("/hello",
web::get().to(hello))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
Listing 2-2 Hello World Actix Application
The core of Listing 2-2 is the App builder in the main() function. The App
struct uses the builder pattern to build a new application instance. When you
call route(), you specify which handler should be called when the user
visits a specific path under the website. In this example, when the user visits
/hello with an HTTP GET method (web::get()), it invokes the hello()
handler.
The hello() handler is an async function that returns something that
implements a Responder trait. A Responder is something that can be
converted into an HTTP response. It’s implemented on common types like
&str, String, and u8 arrays. In this simple example, we respond with an
HttpResponse::Ok() (i.e., status code 200) and a string body “Hello
world”.
An HttpServer wraps the App. The HttpServer handles the incoming
requests and passes them to the App. We bind() an address
(127.0.0.1:8080) to the server so it will listen on the specific IP and port.
Finally, we call run() to start the server and await on it. Notice that the
HttpServer doesn’t take an App instance. Instead, it takes an App factory,
which is a simple closure that creates a new App instance every time. This is
because the HttpServer will create multiple worker threads, each running
one instance of the App. This way, we can better utilize multiple CPU cores
and achieve higher scalability.
You might also notice that the main() function is annotated with an #
[actix_web::main] attribute macro. This attribute tells Actix to execute
the main() function in a special runtime called actix-rt, which is built on
top of the popular Tokio1 runtime.
Note You might be aware that the functions in the “hello world” program
all have async in front, and you need to put .await after them when
calling. This is an important language feature that makes it possible to
build highly-efficient web servers. When you call a normal (i.e., blocking)
function, the whole thread blocks and waits for the function to return. But
if the function is async, it immediately returns a Future instead of
blocking. When you .await on that Future, the program asynchronously
waits for it to complete, which allows other tasks on the same thread to
make progress.
This is extremely important when building web servers. A modern web
server usually needs to handle a large number of clients at the same time. If
the server processes only one thing at a time and blocks whenever it’s
waiting for I/O (input/output) like in a socket communication, it can only
serve one client at a time. One way to solve this is to use an operating
system (OS) construct called a process . A process is an instance of your
server program, and the OS allows you to start multiple processes. This
way, you can have one process handling one client. But processes have a
high overhead so this won’t scale very well.
Another alternative is to use several threads. A thread is a series of
instructions (and their surrounding execution context) that can run
independently of other threads. Threads and processes are implemented
differently in each operating system, but in general, a thread is a
component of a process. Threads in the same process share some common
resources like memory space, so they have a lower overhead to run than a
process. Therefore, we can run more threads than processes on the same
hardware, thus serving more clients.
However, because network I/O is much slower than CPU, most of the
time, the threads are sitting idle, waiting for network I/O. Although threads
are lighter than processes, they still have some overhead. By using
async/await, we can potentially serve multiple clients per thread. When the
server is waiting for a client’s network I/O, it can yield the execution to
other clients served by the same thread.
This is an overly simplified explanation of async/await and how it can
help web development. If you want to learn more about the history and
rationale of Rust’s async/await design, watch Steve Klabnik’s talk called
“Rust’s Journey to Async/Await.”2 You can also read the Asynchronous
Programming in Rust book3.
To run this example, simply run the cargo run command in the terminal
under this project directory. A web server will start on 127.0.0.1:8080, as
we specified. Once the server is running, open a web browser and go to
http://127.0.0.1:8080/hello, and you’ll see the “Hello world” text
(Figure 2-1).
You can put some cat images (in JPEG format) in the static/image
folder. We also need to create an index.css file in static/css that will be
used by static/index.html.
.
+-- Cargo.lock
+-- Cargo.toml
+-- src
| +-- main.rs
+-- static
+-- css
| +-- index.css
+-- image
| +-- british-short-hair.jpg
| +-- persian.jpg
| +-- ragdoll.jpg
+-- index.html
Next, create a file called static/index.html and paste the HTML code
in Listing 2-3 into it.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Catdex</title>
</head>
<body>
<h1>Catdex</h1>
</body>
</html>
Listing 2-3 A Minimal Static HTML
To serve this HTML file, you need to install the actix-files crate. We
already did this in the previous cargo add step. Next, let’s paste the
following code into src/main.rs (Listing 2-4).
use actix_files::{NamedFile};
use actix_web::{web, App, HttpServer, Result};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
println!("Listening on port 8080");
HttpServer::new(|| {
App::new()
.route("/", web::get().to(index))
})
.bind("127.0.0.1:8080")?
.run()
.await
Listing 2-4 Serving the index.html File
The code is almost the same as the “hello world” example, except:
The path is now / (root)
The handler, named index(), now returns a NamedFile
The NamedFile::open() function opens the file in read-only mode.
Because NamedFile implements Responder, we can return it directly in
the handler. It’s wrapped in a Result just in case the file reading failed.
If you run cargo run in a terminal, a server should start on port 8080.
Then you can open a browser and go to http://127.0.0.1:8080/ and
see the contents of index.html being rendered.
Since we are building a cat encyclopedia, we need to add some cat
pictures. You can add the following HTML to static/index.html (Listing
2-5).
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Catdex</title>
<link rel="stylesheet" href="static/css/index.css"
type="text/css">
</head>
<body>
<h1>Catdex</h1>
<section class="cats">
<article class="cat">
<h3>British short hair</h3>
<img src="static/image/british-short-
hair.jpg" />
</article>
<article class="cat">
<h3>Persian</h3>
<img src="static/image/persian.jpg" />
</article>
<article class="cat">
<h3>Ragdoll</h3>
<img src="static/image/ragdoll.jpg" />
</article>
</section>
</body>
</html>
)
Listing 2-5 index.html with External Image and CSS
#[actix_web::main]
async fn main() -> std::io::Result<()> {
println!("Listening on port 8080");
HttpServer::new(|| {
App::new()
.service(
Files::new("/static", "static")
.show_files_listing(),
)
.route("/", web::get().to(index))
})
.bind("127.0.0.1:8080")?
.run()
.await
}
Listing 2-6 Using the Files Service to Serve Static Files
In the App factory, you can use the .service() function to attach a
service to the application. The Files service will serve the static files in a
folder (the second parameter, static) under a certain URL path (the first
parameter, /static). You might notice that we also enabled
.show_files_listing(). When this feature is turned on, you’ll see an
HTML list of all the files under the folder if you open the /static path
(Figure 2-2). This is handy for debugging, but should be turned off in
production to avoid security vulnerabilities4.
[package]
name = "catdex"
Listing 2-7 Cargo.toml for Handlebars
# ...
[dependencies]
# ...
serde_json = "1.0.53"
handlebars = { version = "3.0.1", features =
["dir_source"] }
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>{{project_name}}</title>
<link rel="stylesheet" href="static/css/index.css"
type="text/css">
</head>
<body>
<h1>{{project_name}}</h1>
<section class="cats">
{{#each cats}}
<article class="cat">
<h3>{{this.name}}</h3>
<img src="{{this.image_path}}" />
</article>
{{/each}}
</section>
</body>
</html>
Listing 2-8 Handlebars Template for Catdex
The variables wrapped by {{}} are variables that we’ll provide from the
Rust code later. Notice that there is a {{#each}}...{{/each}} block. This
#each block loops over an array and renders each element once using the
template.
To use this template in the Actix code, you need to paste the code in Listing
2-9 into src/main.rs.
use actix_files::Files;
use actix_web::{web, App, HttpResponse, HttpServer};
use handlebars::Handlebars;
IV
Late in the spring of the year 1865, just as the war had come to a
close, a young invalid officer lay in bed in one of the uppermost
chambers of one of the great New York hotels. His meditations were
interrupted by the entrance of a waiter, who handed him a card
superscribed Mrs. Samuel Mason, and bearing on its reverse the
following words in pencil: "Dear Colonel Mason, I have only just
heard of your being here, ill and alone. It's too dreadful. Do you
remember me? Will you see me? If you do, I think you will remember
me. I insist on coming up. M. M."
Mason was undressed, unshaven, weak, and feverish. His ugly
little hotel chamber was in a state of confusion which had not even
the merit of being picturesque. Mrs. Mason's card was at once a
puzzle and a heavenly intimation of comfort. But all that it
represented was so dim to the young man's enfeebled perception
that it took him some moments to collect his thoughts.
"It's a lady, sir," said the waiter, by way of assisting him.
"Is she young or old?" asked Mason.
"Well, sir, she's a little of both."
"I can't ask a lady to come up here," groaned the invalid.
"Upon my word, sir, you look beautiful," said the waiter. "They like
a sick man. And I see she's of your own name," continued Michael,
in whom constant service had bred great frankness of speech; "the
more shame to her for not coming before."
Colonel Mason concluded that, as the visit had been of Mrs.
Mason's own seeking, he would receive her without more ado. "If
she doesn't mind it, I'm sure I needn't," said the poor fellow, who
hadn't the strength to be over-punctilious. So in a very few moments
his visitor was ushered up to his bedside. He saw before him a
handsome, middle-aged blonde woman, stout of figure, and dressed
in the height of the fashion, who displayed no other embarrassment
than such as was easily explained by the loss of breath consequent
on the ascent of six flights of stairs.
"Do you remember me?" she asked, taking the young man's
hand.
He lay back on his pillow, and looked at her. "You used to be my
aunt,—my aunt Maria," he said.
"I'm your aunt Maria still," she answered. "It's very good of you not
to have forgotten me."
"It's very good of you not to have forgotten me," said Mason, in a
tone which betrayed a deeper feeling than the wish to return a civil
speech.
"Dear me, you've had the war and a hundred dreadful things. I've
been living in Europe, you know. Since my return I've been living in
the country, in your uncle's old house on the river, of which the lease
had just expired when I came home. I came to town yesterday on
business, and accidentally heard of your condition and your
whereabouts. I knew you'd gone into the army, and I had been
wondering a dozen times what had become of you, and whether you
wouldn't turn up now that the war's at last over. Of course I didn't
lose a moment in coming to you. I'm so sorry for you." Mrs. Mason
looked about her for a seat. The chairs were encumbered with odds
and ends belonging to her nephew's wardrobe and to his equipment,
and with the remnants of his last repast. The good lady surveyed the
scene with the beautiful mute irony of compassion.
The young man lay watching her comely face in delicious
submission to whatever form of utterance this feeling might take.
"You're the first woman—to call a woman—I've seen in I don't know
how many months," he said, contrasting her appearance with that of
his room, and reading her thoughts.
"I should suppose so. I mean to be as good as a dozen." She
disembarrassed one of the chairs, and brought it to the bed. Then,
seating herself, she ungloved one of her hands, and laid it softly on
the young man's wrist. "What a great full-grown young fellow you've
become!" she pursued. "Now, tell me, are you very ill?"
"You must ask the doctor," said Mason. "I actually don't know. I'm
extremely uncomfortable, but I suppose it's partly my
circumstances."
"I've no doubt it's more than half your circumstances. I've seen the
doctor. Mrs. Van Zandt is an old friend of mine; and when I come to
town, I always go to see her. It was from her I learned this morning
that you were here in this state. We had begun by rejoicing over the
new prospects of peace; and from that, of course, we had got to
lamenting the numbers of young men who are to enter upon it with
lost limbs and shattered health. It happened that Mrs. Van Zandt
mentioned several of her husband's patients as examples, and
yourself among the number. You were an excellent young man,
miserably sick, without family or friends, and with no asylum but a
suffocating little closet in a noisy hotel. You may imagine that I
pricked up my ears, and asked your baptismal name. Dr. Van Zandt
came in, and told me. Your name is luckily an uncommon one; it's
absurd to suppose that there could be two Ferdinand Masons. In
short, I felt that you were my husband's brother's child, and that at
last I too might have my little turn at hero-nursing. The little that the
Doctor knew of your history agreed with the little that I knew, though I
confess I was sorry to hear that you had never spoken of our
relationship. But why should you? At all events you've got to
acknowledge it now. I regret your not having said something about it
before, only because the Doctor might have brought us together a
month ago, and you would now have been well."
"It will take me more than a month to get well," said Mason,
feeling that, if Mrs. Mason was meaning to exert herself on his
behalf, she should know the real state of the case. "I never spoke of
you, because I had quite lost sight of you. I fancied you were still in
Europe; and indeed," he added, after a moment's hesitation, "I heard
that you had married again."
"Of course you did," said Mrs. Mason, placidly. "I used to hear it
once a month myself. But I had a much better right to fancy you
married. Thank Heaven, however, there's nothing of that sort
between us. We can each do as we please. I promise to cure you in
a month, in spite of yourself."
"What's your remedy?" asked the young man, with a smile very
courteous, considering how sceptical it was.
"My first remedy is to take you out of this horrible hole. I talked it
all over with Dr. Van Zandt. He says you must get into the country.
Why, my dear boy, this is enough to kill you outright,—one Broadway
outside of your window and another outside of your door! Listen to
me. My house is directly on the river, and only two hours' journey by
rail. You know I've no children. My only companion is my niece,
Caroline Hofmann. You shall come and stay with us until you are as
strong as you need be,—if it takes a dozen years. You shall have
sweet, cool air, and proper food, and decent attendance, and the
devotion of a sensible woman. I shall not listen to a word of
objection. You shall do as you please, get up when you please, dine
when you please, go to bed when you please, and say what you
please. I shall ask nothing of you but to let yourself be very dearly
cared for. Do you remember how, when you were a boy at school,
after your father's death, you were taken with measles, and your
uncle had you brought to our own house? I helped to nurse you
myself, and I remember what nice manners you had in the very
midst of your measles. Your uncle was very fond of you; and if he
had had any considerable property of his own, I know he would have
remembered you in his will. But, of course, he couldn't leave away
his wife's money. What I wish to do for you is a very small part of
what he would have done, if he had only lived, and heard of your
gallantry and your sufferings. So it's settled. I shall go home this
afternoon. To-morrow morning I shall despatch my man-servant to
you with instructions. He's an Englishman. He thoroughly knows his
business, and he will put up your things, and save you every particle
of trouble. You've only to let yourself be dressed, and driven to the
train. I shall, of course, meet you at your journey's end. Now don't tell
me you're not strong enough."
"I feel stronger at this moment than I've felt in a dozen weeks,"
said Mason. "It's useless for me to attempt to thank you."
"Quite useless. I shouldn't listen to you. And I suppose," added
Mrs. Mason, looking over the bare walls and scanty furniture of the
room, "you pay a fabulous price for this bower of bliss. Do you need
money?"
The young man shook his head.
"Very well then," resumed Mrs. Mason, conclusively, "from this
moment you're in my hands."
The young man lay speechless from the very fulness of his heart;
but he strove by the pressure of his fingers to give her some
assurance of his gratitude. His companion rose, and lingered beside
him, drawing on her glove, and smiling quietly with the look of a long-
baffled philanthropist who has at last discovered a subject of infinite
capacity. Poor Ferdinand's weary visage reflected her smile. Finally,
after the lapse of years, he too was being cared for. He let his head
sink into the pillow, and silently inhaled the perfume of her sober
elegance and her cordial good-nature. He felt like taking her dress in
his hand, and asking her not to leave him,—now that solitude would
be bitter. His eyes, I suppose, betrayed this touching apprehension,
—doubly touching in a war-wasted young officer. As she prepared to
bid him farewell, Mrs. Mason stooped, and kissed his forehead. He
listened to the rustle of her dress across the carpet, to the gentle
closing of the door, and to her retreating footsteps. And then, giving
way to his weakness, he put his hands to his face, and cried like a
homesick schoolboy. He had been reminded of the exquisite side of
life.
Matters went forward as Mrs. Mason had arranged them. At six
o'clock on the following evening Ferdinand found himself deposited
at one of the way stations of the Hudson River Railroad, exhausted
by his journey, and yet excited at the prospect of its drawing to a
close. Mrs. Mason was in waiting in a low basket-phaeton, with a
magazine of cushions and wrappings. Ferdinand transferred himself
to her side, and they drove rapidly homeward. Mrs. Mason's house
was a cottage of liberal make, with a circular lawn, a sinuous
avenue, and a well-grown plantation of shrubbery. As the phaeton
drew up before the porch, a young lady appeared in the doorway.
Mason will be forgiven if he considered himself presented ex officio,
as I may say, to this young lady. Before he really knew it, and in the
absence of the servant, who, under Mrs. Mason's directions, was
busy in the background with his trunk, he had availed himself of her
proffered arm, and had allowed her to assist him through the porch,
across the hall, and into the parlor, where she graciously consigned
him to a sofa which, for his especial use, she had caused to be
wheeled up before a fire kindled for his especial comfort. He was
unable, however, to take advantage of her good offices. Prudence
dictated that without further delay he should betake himself to his
room.
On the morning after his arrival he got up early, and made an
attempt to be present at breakfast; but his strength failed him, and he
was obliged to dress at his leisure, and content himself with a simple
transition from his bed to his arm-chair. The chamber assigned him
was designedly on the ground-floor, so that he was spared the
trouble of measuring his strength with the staircase,—a charming
room, brightly carpeted and upholstered, and marked by a certain
fastidious freshness which betrayed the uncontested dominion of
women. It had a broad high window, draped in chintz and crisp
muslin and opening upon the greensward of the lawn. At this
window, wrapped in his dressing-gown, and lost in the embrace of
the most unresisting of arm-chairs, he slowly discussed his simple
repast. Before long his hostess made her appearance on the lawn
outside the window. As this quarter of the house was covered with
warm sunshine, Mason ventured to open the window and talk to her,
while she stood out on the grass beneath her parasol.
"It's time to think of your physician," she said. "You shall choose
for yourself. The great physician here is Dr. Gregory, a gentleman of
the old school. We have had him but once, for my niece and I have
the health of a couple of dairy-maids. On that one occasion he—well,
he made a fool of himself. His practice is among the 'old families,'
and he only knows how to treat certain old-fashioned, obsolete
complaints. Anything brought about by the war would be quite out of
his range. And then he vacillates, and talks about his own maladies
à lui. And, to tell the truth, we had a little repartee which makes our
relations somewhat ambiguous."
"I see he would never do," said Mason, laughing. "But he's not
your only physician?"
"No: there is a young man, a newcomer, a Dr. Knight, whom I
don't know, but of whom I've heard very good things. I confess that I
have a prejudice in favor of the young men. Dr. Knight has a position
to establish, and I suppose he's likely to be especially attentive and
careful. I believe, moreover, that he's been an army surgeon."
"I knew a man of his name," said Mason. "I wonder if this is he.
His name was Horace Knight,—a light-haired, near-sighted man."
"I don't know," said Mrs. Mason; "perhaps Caroline knows." She
retreated a few steps, and called to an upper window: "Caroline,
what's Dr. Knight's first name?"
Mason listened to Miss Hofmann's answer,—"I haven't the least
idea."
"Is it Horace?"
"I don't know."
"Is he light or dark?"
"I've never seen him."
"Is he near-sighted?"
"How in the world should I know?"
"I fancy he's as good as any one," said Ferdinand. "With you, my
dear aunt, what does the doctor matter?"
Mrs. Mason accordingly sent for Dr. Knight, who, on arrival, turned
out to be her nephew's old acquaintance. Although the young men
had been united by no greater intimacy than the superficial
comradeship resulting from a winter in neighboring quarters, they
were very well pleased to come together again. Horace Knight was a
young man of good birth, good looks, good faculties, and good
intentions, who, after a three years' practice of surgery in the army,
had undertaken to push his fortune in Mrs. Mason's neighborhood.
His mother, a widow with a small income, had recently removed to
the country for economy, and her son had been unwilling to leave
her to live alone. The adjacent country, moreover, offered a
promising field for a man of energy,—a field well stocked with large
families of easy income and of those conservative habits which lead
people to make much of the cares of a physician. The local
practitioner had survived the glory of his prime, and was not,
perhaps, entirely guiltless of Mrs. Mason's charge, that he had not
kept up with the progress of the "new diseases." The world, in fact,
was getting too new for him, as well as for his old patients. He had
had money invested in the South,—precious sources of revenue,
which the war had swallowed up at a gulp; he had grown frightened
and nervous and querulous; he had lost his presence of mind and
his spectacles in several important conjunctures; he had been
repeatedly and distinctly fallible; a vague dissatisfaction pervaded
the breasts of his patrons; he was without competitors: in short,
fortune was propitious to Dr. Knight. Mason remembered the young
physician only as a good-humored, intelligent companion; but he
soon had reason to believe that his medical skill would leave nothing
to be desired. He arrived rapidly at a clear understanding of
Ferdinand's case; he asked intelligent questions, and gave simple
and definite instructions. The disorder was deeply seated and
virulent, but there was no apparent reason why unflinching care and
prudence should not subdue it.
"Your strength is very much reduced," he said, as he took his hat
and gloves to go; "but I should say you had an excellent constitution.
It seems to me, however,—if you will pardon me for saying so,—to
be partly your own fault that you have fallen so low. You have
opposed no resistance; you haven't cared to get well."
"I confess that I haven't,—particularly. But I don't see how you
should know it."
"Why it's obvious."
"Well, it was natural enough. Until Mrs. Mason discovered me, I
hadn't a friend in the world. I had become demoralized by solitude. I
had almost forgotten the difference between sickness and health. I
had nothing before my eyes to remind me in tangible form of that
great mass of common human interests for the sake of which—
under whatever name he may disguise the impulse—a man
continues in health and recovers from disease. I had forgotten that I
ever cared for books or ideas, or anything but the preservation of my
miserable carcass. My carcass had become quite too miserable to
Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade
Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.
textbookfull.com