Skip to content

Commit b5739d2

Browse files
committed
Prelim support for virtual hosts. Directory listing support. Removed useless create data cache from HTTPMessage. Bug fixes.
1 parent b9bb9bf commit b5739d2

File tree

2 files changed

+251
-0
lines changed

2 files changed

+251
-0
lines changed

ResourceHost.cpp

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
/**
2+
httpserver
3+
ResourceHost.cpp
4+
Copyright 2011-2012 Ramsey Kant
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
*/
18+
19+
#include "ResourceHost.h"
20+
21+
ResourceHost::ResourceHost(std::string base) {
22+
cacheMap = NULL;
23+
diskBasePath = base;
24+
25+
// Check to see if the disk base path is a valid path
26+
27+
28+
// Initialize cache map..possibly preload cache with files as a future feature?
29+
cacheMap = new std::map<std::string, Resource*>();
30+
}
31+
32+
ResourceHost::~ResourceHost() {
33+
clearCache();
34+
35+
// Delete the map instance
36+
delete cacheMap;
37+
}
38+
39+
/**
40+
* Load File
41+
* Read a file from disk and load it into the memory cache
42+
*
43+
* @param path Full disk path of the file
44+
* @param sb Filled in stat struct
45+
* @return Return's the resource object upon successful load
46+
*/
47+
Resource* ResourceHost::loadFile(std::string path, struct stat sb) {
48+
std::ifstream file;
49+
unsigned int len = 0;
50+
51+
// Open the file
52+
file.open(path.c_str(), std::ios::binary);
53+
54+
// Return null if failed
55+
if(!file.is_open())
56+
return NULL;
57+
58+
// Get the length of the file
59+
/*file.seekg(0, std::ios::end);
60+
len = file.tellg();
61+
file.seekg(0, std::ios::beg);*/
62+
len = sb.st_size;
63+
64+
// Allocate memory for contents of file and read in the contents
65+
byte* fdata = new byte[len];
66+
file.read((char*)fdata, len);
67+
68+
// Close the file
69+
file.close();
70+
71+
// Create a new Resource object and setup it's contents
72+
Resource* res = new Resource(path);
73+
res->setData(fdata, len);
74+
75+
// Insert the resource into the map
76+
cacheMap->insert(std::pair<std::string, Resource*>(res->getLocation(), res));
77+
78+
return res;
79+
}
80+
81+
/**
82+
* Dump and delete all resources in the cache, then clear it out
83+
*/
84+
void ResourceHost::clearCache() {
85+
// Cleanup all Resource objects
86+
std::map<std::string, Resource*>::const_iterator it;
87+
for(it = cacheMap->begin(); it != cacheMap->end(); ++it) {
88+
delete it->second;
89+
}
90+
cacheMap->clear();
91+
}
92+
93+
/**
94+
* Return an HTML directory listing provided by the relative path dirPath
95+
*
96+
* @param path Full disk path of the file
97+
* @param uri Relative webserver URI
98+
* @return String representation of the directory. Blank string if invalid directory
99+
*/
100+
std::string ResourceHost::listDirectory(std::string path, std::string uri) {
101+
std::stringstream ret;
102+
ret << "<html><head><title>" << uri << "</title></head><body>";
103+
104+
DIR *dir;
105+
struct dirent *ent;
106+
107+
dir = opendir(path.c_str());
108+
if(dir == NULL)
109+
return "";
110+
111+
// Page title, displaying the URI of the directory being listed
112+
ret << "<h1>Index of " << uri << "</h1><hr><br />";
113+
114+
// Add all files and directories to the return
115+
while((ent = readdir(dir)) != NULL) {
116+
// Skip any 'hidden' files (starting with a '.')
117+
if(ent->d_name[0] == '.')
118+
continue;
119+
120+
// Display link to object in directory:
121+
ret << "<a href=\"" << uri << ent->d_name << "\">" << ent->d_name << "</a><br />";
122+
}
123+
124+
// Close the directory
125+
closedir(dir);
126+
127+
ret << "</body></html>";
128+
129+
return ret.str();
130+
}
131+
132+
/**
133+
* Retrieve a resource from the File system
134+
* The memory cache will be checked before going out to disk
135+
*
136+
* @param uri The URI sent in the request
137+
* @return NULL if unable to load the resource. Resource object
138+
*/
139+
Resource* ResourceHost::getResource(std::string uri) {
140+
if(uri.length() > 255 || uri.empty())
141+
return NULL;
142+
143+
std::string path = diskBasePath + uri;
144+
Resource* res = NULL;
145+
146+
// Check the cache first:
147+
std::map<std::string, Resource*>::const_iterator it;
148+
it = cacheMap->find(path);
149+
// If it isn't the element past the end (end()), then a resource was found
150+
if(it != cacheMap->end()) {
151+
res = it->second;
152+
return res;
153+
}
154+
155+
// Not in cache, check the disk
156+
157+
// Gather info about the resource with stat: determine if it's a directory or file, check if its owned by group/user, modify times
158+
struct stat sb;
159+
if(stat(path.c_str(), &sb) == -1)
160+
return NULL; // File not found
161+
162+
// Make sure the webserver USER owns the files
163+
if(!(sb.st_mode & S_IRWXU))
164+
return NULL;
165+
166+
// Determine file type
167+
if(sb.st_mode & S_IFDIR) { // Directory
168+
// Generate an HTML directory listing
169+
std::string listing = listDirectory(path, uri);
170+
unsigned int slen = listing.length();
171+
char* sdata = new char[slen];
172+
strncpy(sdata, listing.c_str(), slen);
173+
174+
res = new Resource(path, true);
175+
res->setData((byte*)sdata, slen);
176+
177+
// Cache the listing
178+
cacheMap->insert(std::pair<std::string, Resource*>(res->getLocation(), res));
179+
} else if(sb.st_mode & S_IFREG) { // Regular file
180+
// Attempt to load the file into memory from the FS
181+
res = loadFile(path, sb);
182+
} else { // Something else..device, socket, symlink
183+
return NULL;
184+
}
185+
186+
return res;
187+
}

ResourceHost.h

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/**
2+
httpserver
3+
ResourceHost.h
4+
Copyright 2011-2012 Ramsey Kant
5+
6+
Licensed under the Apache License, Version 2.0 (the "License");
7+
you may not use this file except in compliance with the License.
8+
You may obtain a copy of the License at
9+
10+
http://www.apache.org/licenses/LICENSE-2.0
11+
12+
Unless required by applicable law or agreed to in writing, software
13+
distributed under the License is distributed on an "AS IS" BASIS,
14+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
See the License for the specific language governing permissions and
16+
limitations under the License.
17+
*/
18+
19+
#ifndef _RESOURCEHOST_H_
20+
#define _RESOURCEHOST_H_
21+
22+
#include <iostream>
23+
#include <sstream>
24+
#include <string>
25+
#include <map>
26+
#include <dirent.h>
27+
#include <sys/types.h>
28+
#include <sys/stat.h>
29+
#include <unistd.h>
30+
#include <fstream>
31+
32+
#include "Resource.h"
33+
34+
class ResourceHost {
35+
private:
36+
// Local file system base path
37+
std::string diskBasePath;
38+
39+
// Map to track resources only in the memory cache (not on disk)
40+
std::map<std::string, Resource*> *cacheMap;
41+
42+
private:
43+
44+
// Reset's the cache by deleteing all resources from memory and clearing the map
45+
void clearCache();
46+
47+
// Loads a file from the FS into the cache as a Resource
48+
Resource* loadFile(std::string path, struct stat sb);
49+
50+
public:
51+
ResourceHost(std::string base);
52+
~ResourceHost();
53+
54+
// Provide a string rep of the directory listing
55+
std::string listDirectory(std::string dirPath, std::string uri);
56+
57+
// Write a resource to the cache and file system
58+
void putResource(Resource* res, bool writeToDisk);
59+
60+
// Returns a Resource in the cache or file system if it exists
61+
Resource* getResource(std::string uri);
62+
};
63+
64+
#endif

0 commit comments

Comments
 (0)