Mercurial > hg > orthanc
comparison Core/HttpServer/HttpOutput.cpp @ 0:3959d33612cc
initial commit
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Thu, 19 Jul 2012 14:32:22 +0200 |
parents | |
children | 3a584803783e |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:3959d33612cc |
---|---|
1 /** | |
2 * Palantir - A Lightweight, RESTful DICOM Store | |
3 * Copyright (C) 2012 Medical Physics Department, CHU of Liege, | |
4 * Belgium | |
5 * | |
6 * This program is free software: you can redistribute it and/or | |
7 * modify it under the terms of the GNU General Public License as | |
8 * published by the Free Software Foundation, either version 3 of the | |
9 * License, or (at your option) any later version. | |
10 * | |
11 * This program is distributed in the hope that it will be useful, but | |
12 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 * General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License | |
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 **/ | |
19 | |
20 | |
21 #include "HttpOutput.h" | |
22 | |
23 #include <vector> | |
24 #include <stdio.h> | |
25 #include <boost/lexical_cast.hpp> | |
26 #include "../PalantirException.h" | |
27 #include "../Toolbox.h" | |
28 #include "../../PalantirCppClient/HttpException.h" | |
29 | |
30 namespace Palantir | |
31 { | |
32 void HttpOutput::SendString(const std::string& s) | |
33 { | |
34 if (s.size() > 0) | |
35 Send(&s[0], s.size()); | |
36 } | |
37 | |
38 void HttpOutput::SendOkHeader(const std::string& contentType) | |
39 { | |
40 SendOkHeader(contentType.c_str(), false, 0); | |
41 } | |
42 | |
43 void HttpOutput::SendOkHeader() | |
44 { | |
45 SendOkHeader(NULL, false, 0); | |
46 } | |
47 | |
48 void HttpOutput::SendOkHeader(uint64_t contentLength) | |
49 { | |
50 SendOkHeader(NULL, true, contentLength); | |
51 } | |
52 | |
53 void HttpOutput::SendOkHeader(const std::string& contentType, | |
54 uint64_t contentLength) | |
55 { | |
56 SendOkHeader(contentType.c_str(), true, contentLength); | |
57 } | |
58 | |
59 | |
60 void HttpOutput::SendOkHeader(const char* contentType, | |
61 bool hasContentLength, | |
62 size_t contentLength) | |
63 { | |
64 std::string s = "HTTP/1.1 200 OK\r\n"; | |
65 | |
66 if (contentType) | |
67 { | |
68 s += "Content-Type: " + std::string(contentType) + "\r\n"; | |
69 } | |
70 | |
71 if (hasContentLength) | |
72 { | |
73 s += "Content-Length: " + boost::lexical_cast<std::string>(contentLength) + "\r\n"; | |
74 } | |
75 | |
76 s += "\r\n"; | |
77 | |
78 Send(&s[0], s.size()); | |
79 } | |
80 | |
81 | |
82 void HttpOutput::SendMethodNotAllowedError(const std::string& allowed) | |
83 { | |
84 std::string s = | |
85 "HTTP/1.1 405 " + std::string(HttpException::GetDescription(HttpStatus_405_MethodNotAllowed)) + | |
86 "\r\nAllow: " + allowed + | |
87 "\r\n\r\n"; | |
88 Send(&s[0], s.size()); | |
89 } | |
90 | |
91 | |
92 void HttpOutput::SendHeader(HttpStatus status) | |
93 { | |
94 if (status == HttpStatus_200_Ok || | |
95 status == HttpStatus_405_MethodNotAllowed) | |
96 { | |
97 throw PalantirException("Please use the dedicated methods to this HTTP status code in HttpOutput"); | |
98 } | |
99 | |
100 SendHeaderInternal(status); | |
101 } | |
102 | |
103 | |
104 void HttpOutput::SendHeaderInternal(HttpStatus status) | |
105 { | |
106 std::string s = "HTTP/1.1 " + | |
107 boost::lexical_cast<std::string>(status) + | |
108 " " + std::string(HttpException::GetDescription(status)) + | |
109 "\r\n\r\n"; | |
110 Send(&s[0], s.size()); | |
111 } | |
112 | |
113 | |
114 void HttpOutput::AnswerBufferWithContentType(const std::string& buffer, | |
115 const std::string& contentType) | |
116 { | |
117 SendOkHeader(contentType.c_str(), true, buffer.size()); | |
118 SendString(buffer); | |
119 } | |
120 | |
121 | |
122 void HttpOutput::AnswerBufferWithContentType(const void* buffer, | |
123 size_t size, | |
124 const std::string& contentType) | |
125 { | |
126 SendOkHeader(contentType.c_str(), true, size); | |
127 Send(buffer, size); | |
128 } | |
129 | |
130 | |
131 void HttpOutput::AnswerFileWithContentType(const std::string& path, | |
132 const std::string& contentType) | |
133 { | |
134 uint64_t fileSize = Toolbox::GetFileSize(path); | |
135 | |
136 FILE* fp = fopen(path.c_str(), "rb"); | |
137 if (!fp) | |
138 { | |
139 SendHeaderInternal(HttpStatus_500_InternalServerError); | |
140 return; | |
141 } | |
142 | |
143 SendOkHeader(contentType.c_str(), true, fileSize); | |
144 | |
145 std::vector<uint8_t> buffer(1024 * 1024); // Chunks of 1MB | |
146 | |
147 for (;;) | |
148 { | |
149 size_t nbytes = fread(&buffer[0], 1, buffer.size(), fp); | |
150 if (nbytes == 0) | |
151 { | |
152 break; | |
153 } | |
154 else | |
155 { | |
156 Send(&buffer[0], nbytes); | |
157 } | |
158 } | |
159 | |
160 fclose(fp); | |
161 } | |
162 | |
163 | |
164 void HttpOutput::AnswerFileAutodetectContentType(const std::string& path) | |
165 { | |
166 AnswerFileWithContentType(path, Toolbox::AutodetectMimeType(path)); | |
167 } | |
168 | |
169 | |
170 void HttpOutput::AnswerFile(const FileStorage& storage, | |
171 const std::string& uuid, | |
172 const std::string& contentType) | |
173 { | |
174 boost::filesystem::path p(storage.GetPath(uuid)); | |
175 AnswerFileWithContentType(p.string(), contentType); | |
176 } | |
177 | |
178 | |
179 | |
180 void HttpOutput::Redirect(const std::string& path) | |
181 { | |
182 std::string s = | |
183 "HTTP/1.1 301 " + std::string(HttpException::GetDescription(HttpStatus_301_MovedPermanently)) + | |
184 "\r\nLocation: " + path + | |
185 "\r\n\r\n"; | |
186 Send(&s[0], s.size()); | |
187 } | |
188 } |