func (easy *Easy) SetOpt(opt EasyOption, param interface{}) error { switch { case opt >= C.CURLOPTTYPE_OFF_T: return easy.getError(C.my_esetoptl(easy.cptr, C.CURLoption(opt), C.long(param.(int)))) case opt >= C.CURLOPTTYPE_FUNCTIONPOINT: return errors.New("function options not supported by SetOpt()") case opt >= C.CURLOPTTYPE_OBJECTPOINT: if isStringOption(opt) { c_param := C.CString(param.(string)) defer C.free(unsafe.Pointer(c_param)) return easy.getError(C.my_esetoptc(easy.cptr, C.CURLoption(opt), c_param)) } else { return fmt.Errorf("option %d not supported", opt) } case opt >= C.CURLOPTTYPE_LONG: var val C.long switch t := param.(type) { case bool: if t { val = C.long(1) } case int: val = C.long(t) case int32: val = C.long(t) case int64: val = C.long(t) default: panic("CURLOPTTYPE_LONG param must be of golang type bool, int, int32, or int64") } return easy.getError(C.my_esetoptl(easy.cptr, C.CURLoption(opt), val)) } return nil }
// curl_easy_setopt - set options for a curl easy handle // WARNING: a function pointer is &fun, but function addr is reflect.ValueOf(fun).Pointer() func (curl *CURL) Setopt(opt int, param interface{}) error { p := curl.handle if param == nil { // NOTE: some option will crash program when got a nil param return newCurlError(C.curl_easy_setopt_pointer(p, C.CURLoption(opt), nil)) } switch { // not really set case opt == OPT_READDATA: // OPT_INFILE curl.readData = ¶m return nil case opt == OPT_DEBUGDATA: curl.debugData = ¶m return nil case opt == OPT_PROGRESSDATA: curl.progressData = ¶m return nil case opt == OPT_HEADERDATA: // also known as OPT_WRITEHEADER curl.headerData = ¶m return nil case opt == OPT_WRITEDATA: // OPT_FILE curl.writeData = ¶m return nil case opt == OPT_READFUNCTION: fun := param.(func([]byte, interface{}) int) curl.readFunction = &fun ptr := C.return_read_function() if err := newCurlError(C.curl_easy_setopt_pointer(p, C.CURLoption(opt), ptr)); err == nil { return newCurlError(C.curl_easy_setopt_pointer(p, OPT_READDATA, unsafe.Pointer(reflect.ValueOf(curl).Pointer()))) } else { return err } case opt == OPT_PROGRESSFUNCTION: fun := param.(func(float64, float64, float64, float64, interface{}) bool) curl.progressFunction = &fun ptr := C.return_progress_function() if err := newCurlError(C.curl_easy_setopt_pointer(p, C.CURLoption(opt), ptr)); err == nil { return newCurlError(C.curl_easy_setopt_pointer(p, OPT_PROGRESSDATA, unsafe.Pointer(reflect.ValueOf(curl).Pointer()))) } else { return err } case opt == OPT_DEBUGFUNCTION: fun := param.(func(int, []byte) bool) curl.debugFunction = &fun ptr := C.return_debug_function() if err := newCurlError(C.curl_easy_setopt_pointer(p, C.CURLoption(opt), ptr)); err == nil { return newCurlError(C.curl_easy_setopt_pointer(p, OPT_DEBUGDATA, unsafe.Pointer(reflect.ValueOf(curl).Pointer()))) } else { return err } case opt == OPT_HEADERFUNCTION: fun := param.(func([]byte, interface{}) bool) curl.headerFunction = &fun ptr := C.return_header_function() if err := newCurlError(C.curl_easy_setopt_pointer(p, C.CURLoption(opt), ptr)); err == nil { return newCurlError(C.curl_easy_setopt_pointer(p, OPT_HEADERDATA, unsafe.Pointer(reflect.ValueOf(curl).Pointer()))) } else { return err } case opt == OPT_WRITEFUNCTION: fun := param.(func([]byte, interface{}) bool) curl.writeFunction = &fun ptr := C.return_write_function() if err := newCurlError(C.curl_easy_setopt_pointer(p, C.CURLoption(opt), ptr)); err == nil { return newCurlError(C.curl_easy_setopt_pointer(p, OPT_WRITEDATA, unsafe.Pointer(reflect.ValueOf(curl).Pointer()))) } else { return err } // for OPT_HTTPPOST, use struct Form case opt == OPT_HTTPPOST: post := param.(*Form) ptr := post.head return newCurlError(C.curl_easy_setopt_pointer(p, C.CURLoption(opt), unsafe.Pointer(ptr))) case opt >= C.CURLOPTTYPE_OFF_T: val := C.off_t(0) switch t := param.(type) { case int: val = C.off_t(t) case uint64: val = C.off_t(t) default: panic("OFF_T conversion not supported") } return newCurlError(C.curl_easy_setopt_off_t(p, C.CURLoption(opt), val)) case opt >= C.CURLOPTTYPE_FUNCTIONPOINT: // function pointer panic("function pointer not implemented yet!") case opt >= C.CURLOPTTYPE_OBJECTPOINT: switch t := param.(type) { case string: ptr := C.CString(t) curl.mallocAddPtr(ptr) return newCurlError(C.curl_easy_setopt_string(p, C.CURLoption(opt), ptr)) case CurlString: ptr := (*C.char)(t) return newCurlError(C.curl_easy_setopt_string(p, C.CURLoption(opt), ptr)) case []string: if len(t) > 0 { ptr := C.CString(t[0]) curl.mallocAddPtr(ptr) a_slist := C.curl_slist_append(nil, ptr) for _, s := range t[1:] { ptr := C.CString(s) curl.mallocAddPtr(ptr) a_slist = C.curl_slist_append(a_slist, ptr) } return newCurlError(C.curl_easy_setopt_slist(p, C.CURLoption(opt), a_slist)) } else { return newCurlError(C.curl_easy_setopt_slist(p, C.CURLoption(opt), nil)) } case []CurlString: if len(t) > 0 { ptr := (*C.char)(t[0]) a_slist := C.curl_slist_append(nil, ptr) for _, s := range t[1:] { ptr := (*C.char)(s) a_slist = C.curl_slist_append(a_slist, ptr) } return newCurlError(C.curl_easy_setopt_slist(p, C.CURLoption(opt), a_slist)) } else { return newCurlError(C.curl_easy_setopt_slist(p, C.CURLoption(opt), nil)) } default: // It panics if v's Kind is not Chan, Func, Map, Ptr, Slice, or UnsafePointer. // val := reflect.ValueOf(param) //fmt.Printf("DEBUG(Setopt): param=%x\n", val.Pointer()) //println("DEBUG can addr =", val.Pointer(), "opt=", opt) // pass a pointer to GoInterface return newCurlError(C.curl_easy_setopt_pointer(p, C.CURLoption(opt), unsafe.Pointer(¶m))) } case opt >= C.CURLOPTTYPE_LONG: val := C.long(0) switch t := param.(type) { case int: val = C.long(t) case bool: if t { val = 1 } case int64: val = C.long(t) case int32: val = C.long(t) default: panic("not supported converstion to c long") } return newCurlError(C.curl_easy_setopt_long(p, C.CURLoption(opt), val)) } panic("opt param error!") }