# See the License for the specific language governing permissions and
# limitations under the License.
-# Curl services: `CurlHTTPRequest` and `CurlMail`
+# Data transfer with URL syntax
+#
+# Download or upload over HTTP with `CurlHTTPRequest` and send emails with `CurlMail`.
module curl
import native_curl
end
end
-# CURL HTTP Request
+# HTTP request builder
+#
+# The request itself is sent by either `execute` or `download_to_file`.
+# The attributes of this class must be set before calling either of these two methods.
+#
+# ## Minimal usage example
+#
+# ~~~
+# var request = new CurlHTTPRequest("http://example.org/")
+# var response = request.execute
+# if response isa CurlResponseSuccess then
+# print "Response status code: {response.status_code}"
+# print response.body_str
+# else if response isa CurlResponseFailed then
+# print_error response.error_msg
+# end
+# ~~~
class CurlHTTPRequest
super CurlRequest
super NativeCurlCallbacks
+ # Address of the remote resource to request
var url: String
- var datas: nullable HeaderMap = null is writable
- var headers: nullable HeaderMap = null is writable
- var delegate: nullable CurlCallbacks = null is writable
+
+ # Data for the body of a POST request
+ var data: nullable HeaderMap is writable
+
+ # Header content of the request
+ var headers: nullable HeaderMap is writable
+
+ # Delegates to customize the behavior when running `execute`
+ var delegate: nullable CurlCallbacks is writable
# Set the user agent for all following HTTP requests
- fun user_agent=(name: String)
- do
- curl.native.easy_setopt(new CURLOption.user_agent, name)
- end
+ var user_agent: nullable String is writable
- # Execute HTTP request with settings configured through attribute
+ # Execute HTTP request
+ #
+ # By default, the response body is returned in an instance of `CurlResponse`.
+ # This behavior can be customized by setting a custom `delegate`.
fun execute: CurlResponse
do
if not self.curl.is_ok then return answer_failure(0, "Curl instance is not correctly initialized")
err = self.curl.native.easy_setopt(new CURLOption.url, url)
if not err.is_ok then return answer_failure(err.to_i, err.to_s)
+ var user_agent = user_agent
+ if user_agent != null then
+ err = curl.native.easy_setopt(new CURLOption.user_agent, user_agent)
+ if not err.is_ok then return answer_failure(err.to_i, err.to_s)
+ end
+
# Callbacks
err = self.curl.native.register_callback_header(callback_receiver)
if not err.is_ok then return answer_failure(err.to_i, err.to_s)
end
# Datas
- var datas = self.datas
- if datas != null then
- var postdatas = datas.to_url_encoded(self.curl)
+ var data = self.data
+ if data != null then
+ var postdatas = data.to_url_encoded(self.curl)
err = self.curl.native.easy_setopt(new CURLOption.postfields, postdatas)
if not err.is_ok then return answer_failure(err.to_i, err.to_s)
end
if err_resp != null then return err_resp
var st_code = self.curl.native.easy_getinfo_long(new CURLInfoLong.response_code)
- if not st_code == null then success_response.status_code = st_code.response
+ if not st_code == null then success_response.status_code = st_code
return success_response
end
if not output_file_name == null then
opt_name = output_file_name
else if not self.url.substring(self.url.length-1, self.url.length) == "/" then
- opt_name = self.url.basename("")
+ opt_name = self.url.basename
else
return answer_failure(0, "Unable to extract file name, please specify one")
end
if err_resp != null then return err_resp
var st_code = self.curl.native.easy_getinfo_long(new CURLInfoLong.response_code)
- if not st_code == null then success_response.status_code = st_code.response
+ if not st_code == null then success_response.status_code = st_code
var speed = self.curl.native.easy_getinfo_double(new CURLInfoDouble.speed_download)
- if not speed == null then success_response.speed_download = speed.response
+ if not speed == null then success_response.speed_download = speed
var size = self.curl.native.easy_getinfo_double(new CURLInfoDouble.size_download)
- if not size == null then success_response.size_download = size.response
+ if not size == null then success_response.size_download = size
var time = self.curl.native.easy_getinfo_double(new CURLInfoDouble.total_time)
- if not time == null then success_response.total_time = time.response
+ if not time == null then success_response.total_time = time
success_response.file.close
end
# CURL Mail Request
+#
+# ~~~
+# # Craft mail
+# var mail = new CurlMail("sender@example.org",
+# to=["to@example.org"], cc=["bob@example.org"])
+#
+# mail.headers_body["Content-Type:"] = """text/html; charset="UTF-8""""
+# mail.headers_body["Content-Transfer-Encoding:"] = "quoted-printable"
+#
+# mail.body = "<h1>Here you can write HTML stuff.</h1>"
+# mail.subject = "Hello From My Nit Program"
+#
+# # Set mail server
+# var error = mail.set_outgoing_server("smtps://smtp.example.org:465",
+# "user@example.org", "mypassword")
+# if error != null then
+# print "Mail Server Error: {error}"
+# exit 0
+# end
+#
+# # Send
+# error = mail.execute
+# if error != null then
+# print "Transfer Error: {error}"
+# exit 0
+# end
+# ~~~
class CurlMail
super CurlRequest
super NativeCurlCallbacks
# Content header
var headers_body = new HeaderMap is lazy, writable
- private var supported_outgoing_protocol: Array[String] = ["smtp", "smtps"]
+ # Protocols supported to send mail to a server
+ #
+ # Default value at `["smtp", "smtps"]`
+ var supported_outgoing_protocol: Array[String] = ["smtp", "smtps"]
# Helper method to add pair values to mail content while building it (ex: "To:", "address@mail.com")
private fun add_pair_to_content(str: String, att: String, val: nullable String): String
var error_code: Int
var error_msg: String
+
+ redef fun to_s do return "{error_msg} ({error_code})"
end
# Success Abstract Response Success Class
super CurlResponseSuccessIntern
var status_code = 0
- var speed_download = 0
- var size_download = 0
- var total_time = 0
+ var speed_download = 0.0
+ var size_download = 0.0
+ var total_time = 0.0
private var file: nullable FileWriter = null
# Receive bytes stream from request due to stream callback registering