X-Git-Url: http://nitlanguage.org diff --git a/lib/curl/curl.nit b/lib/curl/curl.nit index 2921fa1..f225a02 100644 --- a/lib/curl/curl.nit +++ b/lib/curl/curl.nit @@ -14,34 +14,42 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Network functionnalities based on Curl_c module. +# Data transfer with URL syntax +# +# Download or upload over HTTP with `CurlHTTPRequest` and send emails with `CurlMail`. module curl import native_curl -# Top level of Curl +redef class Sys + # Shared Curl library handle + # + # Usually, you do not have to use this attribute, it instancied by `CurlHTTPRequest` and `CurlMail`. + # But in some cases you may want to finalize it to free some small resources. + # However, if Curl services are needed once again, this attribute must be manually set. + var curl: Curl = new Curl is lazy, writable +end + +# Curl library handle, it is initialized and released with this class class Curl + super FinalizableOnce - protected var native = new NativeCurl.easy_init + private var native = new NativeCurl.easy_init # Check for correct initialization fun is_ok: Bool do return self.native.is_init - # Release Curl instance - fun destroy do self.native.easy_clean + redef fun finalize_once do if is_ok then native.easy_clean end # CURL Request class CurlRequest - private var curl: Curl + private var curl: Curl = sys.curl # Shall this request be verbose? var verbose: Bool = false is writable - # Launch request method - fun execute: CurlResponse is abstract - # Intern perform method, lowest level of request launching private fun perform: nullable CurlResponseFailed do @@ -71,18 +79,15 @@ class CurlHTTPRequest super NativeCurlCallbacks var url: String - var datas: nullable HeaderMap = null is writable - var headers: nullable HeaderMap = null is writable - var delegate: nullable CurlCallbacks = null is writable + var datas: nullable HeaderMap is writable + var headers: nullable HeaderMap is writable + 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 - redef fun execute + fun execute: CurlResponse do if not self.curl.is_ok then return answer_failure(0, "Curl instance is not correctly initialized") @@ -98,6 +103,12 @@ class CurlHTTPRequest 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) @@ -125,7 +136,7 @@ class CurlHTTPRequest 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 @@ -156,7 +167,7 @@ class CurlHTTPRequest 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 @@ -170,16 +181,16 @@ class CurlHTTPRequest 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 @@ -188,6 +199,33 @@ class CurlHTTPRequest 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 = "

Here you can write HTML stuff.

" +# 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 @@ -216,7 +254,10 @@ class CurlMail # 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 @@ -268,7 +309,7 @@ class CurlMail end # Execute Mail request with settings configured through attribute - redef fun execute + fun execute: nullable CurlResponseFailed do if not self.curl.is_ok then return answer_failure(0, "Curl instance is not correctly initialized") @@ -343,7 +384,7 @@ class CurlMail var err_resp = perform if err_resp != null then return err_resp - return new CurlMailResponseSuccess + return null end end @@ -362,6 +403,8 @@ class CurlResponseFailed var error_code: Int var error_msg: String + + redef fun to_s do return "{error_msg} ({error_code})" end # Success Abstract Response Success Class @@ -395,19 +438,14 @@ class CurlResponseSuccess end end -# Success Response Class of mail request -class CurlMailResponseSuccess - super CurlResponseSuccessIntern -end - # Success Response Class of a downloaded File class CurlFileResponseSuccess 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