You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

convert.go 32 kB

4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880
  1. // Copyright 2019 Huawei Technologies Co.,Ltd.
  2. // Licensed under the Apache License, Version 2.0 (the "License"); you may not use
  3. // this file except in compliance with the License. You may obtain a copy of the
  4. // License at
  5. //
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software distributed
  9. // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  10. // CONDITIONS OF ANY KIND, either express or implied. See the License for the
  11. // specific language governing permissions and limitations under the License.
  12. //nolint:golint, unused
  13. package obs
  14. import (
  15. "bytes"
  16. "encoding/json"
  17. "fmt"
  18. "io"
  19. "io/ioutil"
  20. "net/http"
  21. "reflect"
  22. "strings"
  23. "time"
  24. )
  25. func cleanHeaderPrefix(header http.Header) map[string][]string {
  26. responseHeaders := make(map[string][]string)
  27. for key, value := range header {
  28. if len(value) > 0 {
  29. key = strings.ToLower(key)
  30. if strings.HasPrefix(key, HEADER_PREFIX) || strings.HasPrefix(key, HEADER_PREFIX_OBS) {
  31. key = key[len(HEADER_PREFIX):]
  32. }
  33. responseHeaders[key] = value
  34. }
  35. }
  36. return responseHeaders
  37. }
  38. // ParseStringToEventType converts string value to EventType value and returns it
  39. func ParseStringToEventType(value string) (ret EventType) {
  40. switch value {
  41. case "ObjectCreated:*", "s3:ObjectCreated:*":
  42. ret = ObjectCreatedAll
  43. case "ObjectCreated:Put", "s3:ObjectCreated:Put":
  44. ret = ObjectCreatedPut
  45. case "ObjectCreated:Post", "s3:ObjectCreated:Post":
  46. ret = ObjectCreatedPost
  47. case "ObjectCreated:Copy", "s3:ObjectCreated:Copy":
  48. ret = ObjectCreatedCopy
  49. case "ObjectCreated:CompleteMultipartUpload", "s3:ObjectCreated:CompleteMultipartUpload":
  50. ret = ObjectCreatedCompleteMultipartUpload
  51. case "ObjectRemoved:*", "s3:ObjectRemoved:*":
  52. ret = ObjectRemovedAll
  53. case "ObjectRemoved:Delete", "s3:ObjectRemoved:Delete":
  54. ret = ObjectRemovedDelete
  55. case "ObjectRemoved:DeleteMarkerCreated", "s3:ObjectRemoved:DeleteMarkerCreated":
  56. ret = ObjectRemovedDeleteMarkerCreated
  57. default:
  58. ret = ""
  59. }
  60. return
  61. }
  62. // ParseStringToStorageClassType converts string value to StorageClassType value and returns it
  63. func ParseStringToStorageClassType(value string) (ret StorageClassType) {
  64. switch value {
  65. case "STANDARD":
  66. ret = StorageClassStandard
  67. case "STANDARD_IA", "WARM":
  68. ret = StorageClassWarm
  69. case "GLACIER", "COLD":
  70. ret = StorageClassCold
  71. default:
  72. ret = ""
  73. }
  74. return
  75. }
  76. func prepareGrantURI(grant Grant) string {
  77. if grant.Grantee.URI == GroupAllUsers || grant.Grantee.URI == GroupAuthenticatedUsers {
  78. return fmt.Sprintf("<URI>%s%s</URI>", "http://acs.amazonaws.com/groups/global/", grant.Grantee.URI)
  79. }
  80. if grant.Grantee.URI == GroupLogDelivery {
  81. return fmt.Sprintf("<URI>%s%s</URI>", "http://acs.amazonaws.com/groups/s3/", grant.Grantee.URI)
  82. }
  83. return fmt.Sprintf("<URI>%s</URI>", grant.Grantee.URI)
  84. }
  85. func convertGrantToXML(grant Grant, isObs bool, isBucket bool) string {
  86. xml := make([]string, 0, 4)
  87. if grant.Grantee.Type == GranteeUser {
  88. if isObs {
  89. xml = append(xml, "<Grant><Grantee>")
  90. } else {
  91. xml = append(xml, fmt.Sprintf("<Grant><Grantee xsi:type=\"%s\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">", grant.Grantee.Type))
  92. }
  93. if grant.Grantee.ID != "" {
  94. granteeID := XmlTranscoding(grant.Grantee.ID)
  95. xml = append(xml, fmt.Sprintf("<ID>%s</ID>", granteeID))
  96. }
  97. if !isObs && grant.Grantee.DisplayName != "" {
  98. granteeDisplayName := XmlTranscoding(grant.Grantee.DisplayName)
  99. xml = append(xml, fmt.Sprintf("<DisplayName>%s</DisplayName>", granteeDisplayName))
  100. }
  101. xml = append(xml, "</Grantee>")
  102. } else {
  103. if !isObs {
  104. xml = append(xml, fmt.Sprintf("<Grant><Grantee xsi:type=\"%s\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">", grant.Grantee.Type))
  105. xml = append(xml, prepareGrantURI(grant))
  106. xml = append(xml, "</Grantee>")
  107. } else if grant.Grantee.URI == GroupAllUsers {
  108. xml = append(xml, "<Grant><Grantee>")
  109. xml = append(xml, fmt.Sprintf("<Canned>Everyone</Canned>"))
  110. xml = append(xml, "</Grantee>")
  111. } else {
  112. return strings.Join(xml, "")
  113. }
  114. }
  115. xml = append(xml, fmt.Sprintf("<Permission>%s</Permission>", grant.Permission))
  116. if isObs && isBucket {
  117. xml = append(xml, fmt.Sprintf("<Delivered>%t</Delivered>", grant.Delivered))
  118. }
  119. xml = append(xml, fmt.Sprintf("</Grant>"))
  120. return strings.Join(xml, "")
  121. }
  122. func hasLoggingTarget(input BucketLoggingStatus) bool {
  123. if input.TargetBucket != "" || input.TargetPrefix != "" || len(input.TargetGrants) > 0 {
  124. return true
  125. }
  126. return false
  127. }
  128. // ConvertLoggingStatusToXml converts BucketLoggingStatus value to XML data and returns it
  129. func ConvertLoggingStatusToXml(input BucketLoggingStatus, returnMd5 bool, isObs bool) (data string, md5 string) {
  130. grantsLength := len(input.TargetGrants)
  131. xml := make([]string, 0, 8+grantsLength)
  132. xml = append(xml, "<BucketLoggingStatus>")
  133. if isObs && input.Agency != "" {
  134. agency := XmlTranscoding(input.Agency)
  135. xml = append(xml, fmt.Sprintf("<Agency>%s</Agency>", agency))
  136. }
  137. if hasLoggingTarget(input) {
  138. xml = append(xml, "<LoggingEnabled>")
  139. if input.TargetBucket != "" {
  140. xml = append(xml, fmt.Sprintf("<TargetBucket>%s</TargetBucket>", input.TargetBucket))
  141. }
  142. if input.TargetPrefix != "" {
  143. targetPrefix := XmlTranscoding(input.TargetPrefix)
  144. xml = append(xml, fmt.Sprintf("<TargetPrefix>%s</TargetPrefix>", targetPrefix))
  145. }
  146. if grantsLength > 0 {
  147. xml = append(xml, "<TargetGrants>")
  148. for _, grant := range input.TargetGrants {
  149. xml = append(xml, convertGrantToXML(grant, isObs, false))
  150. }
  151. xml = append(xml, "</TargetGrants>")
  152. }
  153. xml = append(xml, "</LoggingEnabled>")
  154. }
  155. xml = append(xml, "</BucketLoggingStatus>")
  156. data = strings.Join(xml, "")
  157. if returnMd5 {
  158. md5 = Base64Md5([]byte(data))
  159. }
  160. return
  161. }
  162. // ConvertAclToXml converts AccessControlPolicy value to XML data and returns it
  163. func ConvertAclToXml(input AccessControlPolicy, returnMd5 bool, isObs bool) (data string, md5 string) {
  164. xml := make([]string, 0, 4+len(input.Grants))
  165. ownerID := XmlTranscoding(input.Owner.ID)
  166. xml = append(xml, fmt.Sprintf("<AccessControlPolicy><Owner><ID>%s</ID>", ownerID))
  167. if !isObs && input.Owner.DisplayName != "" {
  168. ownerDisplayName := XmlTranscoding(input.Owner.DisplayName)
  169. xml = append(xml, fmt.Sprintf("<DisplayName>%s</DisplayName>", ownerDisplayName))
  170. }
  171. if isObs && input.Delivered != "" {
  172. objectDelivered := XmlTranscoding(input.Delivered)
  173. xml = append(xml, fmt.Sprintf("</Owner><Delivered>%s</Delivered><AccessControlList>", objectDelivered))
  174. } else {
  175. xml = append(xml, "</Owner><AccessControlList>")
  176. }
  177. for _, grant := range input.Grants {
  178. xml = append(xml, convertGrantToXML(grant, isObs, false))
  179. }
  180. xml = append(xml, "</AccessControlList></AccessControlPolicy>")
  181. data = strings.Join(xml, "")
  182. if returnMd5 {
  183. md5 = Base64Md5([]byte(data))
  184. }
  185. return
  186. }
  187. func convertBucketACLToXML(input AccessControlPolicy, returnMd5 bool, isObs bool) (data string, md5 string) {
  188. xml := make([]string, 0, 4+len(input.Grants))
  189. ownerID := XmlTranscoding(input.Owner.ID)
  190. xml = append(xml, fmt.Sprintf("<AccessControlPolicy><Owner><ID>%s</ID>", ownerID))
  191. if !isObs && input.Owner.DisplayName != "" {
  192. ownerDisplayName := XmlTranscoding(input.Owner.DisplayName)
  193. xml = append(xml, fmt.Sprintf("<DisplayName>%s</DisplayName>", ownerDisplayName))
  194. }
  195. xml = append(xml, "</Owner><AccessControlList>")
  196. for _, grant := range input.Grants {
  197. xml = append(xml, convertGrantToXML(grant, isObs, true))
  198. }
  199. xml = append(xml, "</AccessControlList></AccessControlPolicy>")
  200. data = strings.Join(xml, "")
  201. if returnMd5 {
  202. md5 = Base64Md5([]byte(data))
  203. }
  204. return
  205. }
  206. func convertConditionToXML(condition Condition) string {
  207. xml := make([]string, 0, 2)
  208. if condition.KeyPrefixEquals != "" {
  209. keyPrefixEquals := XmlTranscoding(condition.KeyPrefixEquals)
  210. xml = append(xml, fmt.Sprintf("<KeyPrefixEquals>%s</KeyPrefixEquals>", keyPrefixEquals))
  211. }
  212. if condition.HttpErrorCodeReturnedEquals != "" {
  213. xml = append(xml, fmt.Sprintf("<HttpErrorCodeReturnedEquals>%s</HttpErrorCodeReturnedEquals>", condition.HttpErrorCodeReturnedEquals))
  214. }
  215. if len(xml) > 0 {
  216. return fmt.Sprintf("<Condition>%s</Condition>", strings.Join(xml, ""))
  217. }
  218. return ""
  219. }
  220. func prepareRoutingRule(input BucketWebsiteConfiguration) string {
  221. xml := make([]string, 0, len(input.RoutingRules)*10)
  222. for _, routingRule := range input.RoutingRules {
  223. xml = append(xml, "<RoutingRule>")
  224. xml = append(xml, "<Redirect>")
  225. if routingRule.Redirect.Protocol != "" {
  226. xml = append(xml, fmt.Sprintf("<Protocol>%s</Protocol>", routingRule.Redirect.Protocol))
  227. }
  228. if routingRule.Redirect.HostName != "" {
  229. xml = append(xml, fmt.Sprintf("<HostName>%s</HostName>", routingRule.Redirect.HostName))
  230. }
  231. if routingRule.Redirect.ReplaceKeyPrefixWith != "" {
  232. replaceKeyPrefixWith := XmlTranscoding(routingRule.Redirect.ReplaceKeyPrefixWith)
  233. xml = append(xml, fmt.Sprintf("<ReplaceKeyPrefixWith>%s</ReplaceKeyPrefixWith>", replaceKeyPrefixWith))
  234. }
  235. if routingRule.Redirect.ReplaceKeyWith != "" {
  236. replaceKeyWith := XmlTranscoding(routingRule.Redirect.ReplaceKeyWith)
  237. xml = append(xml, fmt.Sprintf("<ReplaceKeyWith>%s</ReplaceKeyWith>", replaceKeyWith))
  238. }
  239. if routingRule.Redirect.HttpRedirectCode != "" {
  240. xml = append(xml, fmt.Sprintf("<HttpRedirectCode>%s</HttpRedirectCode>", routingRule.Redirect.HttpRedirectCode))
  241. }
  242. xml = append(xml, "</Redirect>")
  243. if ret := convertConditionToXML(routingRule.Condition); ret != "" {
  244. xml = append(xml, ret)
  245. }
  246. xml = append(xml, "</RoutingRule>")
  247. }
  248. return strings.Join(xml, "")
  249. }
  250. // ConvertWebsiteConfigurationToXml converts BucketWebsiteConfiguration value to XML data and returns it
  251. func ConvertWebsiteConfigurationToXml(input BucketWebsiteConfiguration, returnMd5 bool) (data string, md5 string) {
  252. routingRuleLength := len(input.RoutingRules)
  253. xml := make([]string, 0, 6+routingRuleLength*10)
  254. xml = append(xml, "<WebsiteConfiguration>")
  255. if input.RedirectAllRequestsTo.HostName != "" {
  256. xml = append(xml, fmt.Sprintf("<RedirectAllRequestsTo><HostName>%s</HostName>", input.RedirectAllRequestsTo.HostName))
  257. if input.RedirectAllRequestsTo.Protocol != "" {
  258. xml = append(xml, fmt.Sprintf("<Protocol>%s</Protocol>", input.RedirectAllRequestsTo.Protocol))
  259. }
  260. xml = append(xml, "</RedirectAllRequestsTo>")
  261. } else {
  262. if input.IndexDocument.Suffix != "" {
  263. indexDocumentSuffix := XmlTranscoding(input.IndexDocument.Suffix)
  264. xml = append(xml, fmt.Sprintf("<IndexDocument><Suffix>%s</Suffix></IndexDocument>", indexDocumentSuffix))
  265. }
  266. if input.ErrorDocument.Key != "" {
  267. errorDocumentKey := XmlTranscoding(input.ErrorDocument.Key)
  268. xml = append(xml, fmt.Sprintf("<ErrorDocument><Key>%s</Key></ErrorDocument>", errorDocumentKey))
  269. }
  270. if routingRuleLength > 0 {
  271. xml = append(xml, "<RoutingRules>")
  272. xml = append(xml, prepareRoutingRule(input))
  273. xml = append(xml, "</RoutingRules>")
  274. }
  275. }
  276. xml = append(xml, "</WebsiteConfiguration>")
  277. data = strings.Join(xml, "")
  278. if returnMd5 {
  279. md5 = Base64Md5([]byte(data))
  280. }
  281. return
  282. }
  283. func convertTransitionsToXML(transitions []Transition, isObs bool) string {
  284. if length := len(transitions); length > 0 {
  285. xml := make([]string, 0, length)
  286. for _, transition := range transitions {
  287. var temp string
  288. if transition.Days > 0 {
  289. temp = fmt.Sprintf("<Days>%d</Days>", transition.Days)
  290. } else if !transition.Date.IsZero() {
  291. temp = fmt.Sprintf("<Date>%s</Date>", transition.Date.UTC().Format(ISO8601_MIDNIGHT_DATE_FORMAT))
  292. }
  293. if temp != "" {
  294. if !isObs {
  295. storageClass := string(transition.StorageClass)
  296. if transition.StorageClass == StorageClassWarm {
  297. storageClass = string(storageClassStandardIA)
  298. } else if transition.StorageClass == StorageClassCold {
  299. storageClass = string(storageClassGlacier)
  300. }
  301. xml = append(xml, fmt.Sprintf("<Transition>%s<StorageClass>%s</StorageClass></Transition>", temp, storageClass))
  302. } else {
  303. xml = append(xml, fmt.Sprintf("<Transition>%s<StorageClass>%s</StorageClass></Transition>", temp, transition.StorageClass))
  304. }
  305. }
  306. }
  307. return strings.Join(xml, "")
  308. }
  309. return ""
  310. }
  311. func convertExpirationToXML(expiration Expiration) string {
  312. if expiration.Days > 0 {
  313. return fmt.Sprintf("<Expiration><Days>%d</Days></Expiration>", expiration.Days)
  314. } else if !expiration.Date.IsZero() {
  315. return fmt.Sprintf("<Expiration><Date>%s</Date></Expiration>", expiration.Date.UTC().Format(ISO8601_MIDNIGHT_DATE_FORMAT))
  316. }
  317. return ""
  318. }
  319. func convertNoncurrentVersionTransitionsToXML(noncurrentVersionTransitions []NoncurrentVersionTransition, isObs bool) string {
  320. if length := len(noncurrentVersionTransitions); length > 0 {
  321. xml := make([]string, 0, length)
  322. for _, noncurrentVersionTransition := range noncurrentVersionTransitions {
  323. if noncurrentVersionTransition.NoncurrentDays > 0 {
  324. storageClass := string(noncurrentVersionTransition.StorageClass)
  325. if !isObs {
  326. if storageClass == string(StorageClassWarm) {
  327. storageClass = string(storageClassStandardIA)
  328. } else if storageClass == string(StorageClassCold) {
  329. storageClass = string(storageClassGlacier)
  330. }
  331. }
  332. xml = append(xml, fmt.Sprintf("<NoncurrentVersionTransition><NoncurrentDays>%d</NoncurrentDays>"+
  333. "<StorageClass>%s</StorageClass></NoncurrentVersionTransition>",
  334. noncurrentVersionTransition.NoncurrentDays, storageClass))
  335. }
  336. }
  337. return strings.Join(xml, "")
  338. }
  339. return ""
  340. }
  341. func convertNoncurrentVersionExpirationToXML(noncurrentVersionExpiration NoncurrentVersionExpiration) string {
  342. if noncurrentVersionExpiration.NoncurrentDays > 0 {
  343. return fmt.Sprintf("<NoncurrentVersionExpiration><NoncurrentDays>%d</NoncurrentDays></NoncurrentVersionExpiration>", noncurrentVersionExpiration.NoncurrentDays)
  344. }
  345. return ""
  346. }
  347. // ConvertLifecyleConfigurationToXml converts BucketLifecyleConfiguration value to XML data and returns it
  348. func ConvertLifecyleConfigurationToXml(input BucketLifecyleConfiguration, returnMd5 bool, isObs bool) (data string, md5 string) {
  349. xml := make([]string, 0, 2+len(input.LifecycleRules)*9)
  350. xml = append(xml, "<LifecycleConfiguration>")
  351. for _, lifecyleRule := range input.LifecycleRules {
  352. xml = append(xml, "<Rule>")
  353. if lifecyleRule.ID != "" {
  354. lifecyleRuleID := XmlTranscoding(lifecyleRule.ID)
  355. xml = append(xml, fmt.Sprintf("<ID>%s</ID>", lifecyleRuleID))
  356. }
  357. lifecyleRulePrefix := XmlTranscoding(lifecyleRule.Prefix)
  358. xml = append(xml, fmt.Sprintf("<Prefix>%s</Prefix>", lifecyleRulePrefix))
  359. xml = append(xml, fmt.Sprintf("<Status>%s</Status>", lifecyleRule.Status))
  360. if ret := convertTransitionsToXML(lifecyleRule.Transitions, isObs); ret != "" {
  361. xml = append(xml, ret)
  362. }
  363. if ret := convertExpirationToXML(lifecyleRule.Expiration); ret != "" {
  364. xml = append(xml, ret)
  365. }
  366. if ret := convertNoncurrentVersionTransitionsToXML(lifecyleRule.NoncurrentVersionTransitions, isObs); ret != "" {
  367. xml = append(xml, ret)
  368. }
  369. if ret := convertNoncurrentVersionExpirationToXML(lifecyleRule.NoncurrentVersionExpiration); ret != "" {
  370. xml = append(xml, ret)
  371. }
  372. xml = append(xml, "</Rule>")
  373. }
  374. xml = append(xml, "</LifecycleConfiguration>")
  375. data = strings.Join(xml, "")
  376. if returnMd5 {
  377. md5 = Base64Md5([]byte(data))
  378. }
  379. return
  380. }
  381. func converntFilterRulesToXML(filterRules []FilterRule, isObs bool) string {
  382. if length := len(filterRules); length > 0 {
  383. xml := make([]string, 0, length*4)
  384. for _, filterRule := range filterRules {
  385. xml = append(xml, "<FilterRule>")
  386. if filterRule.Name != "" {
  387. filterRuleName := XmlTranscoding(filterRule.Name)
  388. xml = append(xml, fmt.Sprintf("<Name>%s</Name>", filterRuleName))
  389. }
  390. if filterRule.Value != "" {
  391. filterRuleValue := XmlTranscoding(filterRule.Value)
  392. xml = append(xml, fmt.Sprintf("<Value>%s</Value>", filterRuleValue))
  393. }
  394. xml = append(xml, "</FilterRule>")
  395. }
  396. if !isObs {
  397. return fmt.Sprintf("<Filter><S3Key>%s</S3Key></Filter>", strings.Join(xml, ""))
  398. }
  399. return fmt.Sprintf("<Filter><Object>%s</Object></Filter>", strings.Join(xml, ""))
  400. }
  401. return ""
  402. }
  403. func converntEventsToXML(events []EventType, isObs bool) string {
  404. if length := len(events); length > 0 {
  405. xml := make([]string, 0, length)
  406. if !isObs {
  407. for _, event := range events {
  408. xml = append(xml, fmt.Sprintf("<Event>%s%s</Event>", "s3:", event))
  409. }
  410. } else {
  411. for _, event := range events {
  412. xml = append(xml, fmt.Sprintf("<Event>%s</Event>", event))
  413. }
  414. }
  415. return strings.Join(xml, "")
  416. }
  417. return ""
  418. }
  419. func converntConfigureToXML(topicConfiguration TopicConfiguration, xmlElem string, isObs bool) string {
  420. xml := make([]string, 0, 6)
  421. xml = append(xml, xmlElem)
  422. if topicConfiguration.ID != "" {
  423. topicConfigurationID := XmlTranscoding(topicConfiguration.ID)
  424. xml = append(xml, fmt.Sprintf("<Id>%s</Id>", topicConfigurationID))
  425. }
  426. topicConfigurationTopic := XmlTranscoding(topicConfiguration.Topic)
  427. xml = append(xml, fmt.Sprintf("<Topic>%s</Topic>", topicConfigurationTopic))
  428. if ret := converntEventsToXML(topicConfiguration.Events, isObs); ret != "" {
  429. xml = append(xml, ret)
  430. }
  431. if ret := converntFilterRulesToXML(topicConfiguration.FilterRules, isObs); ret != "" {
  432. xml = append(xml, ret)
  433. }
  434. tempElem := xmlElem[0:1] + "/" + xmlElem[1:]
  435. xml = append(xml, tempElem)
  436. return strings.Join(xml, "")
  437. }
  438. // ConverntObsRestoreToXml converts RestoreObjectInput value to XML data and returns it
  439. func ConverntObsRestoreToXml(restoreObjectInput RestoreObjectInput) string {
  440. xml := make([]string, 0, 2)
  441. xml = append(xml, fmt.Sprintf("<RestoreRequest><Days>%d</Days>", restoreObjectInput.Days))
  442. if restoreObjectInput.Tier != "Bulk" {
  443. xml = append(xml, fmt.Sprintf("<RestoreJob><Tier>%s</Tier></RestoreJob>", restoreObjectInput.Tier))
  444. }
  445. xml = append(xml, fmt.Sprintf("</RestoreRequest>"))
  446. data := strings.Join(xml, "")
  447. return data
  448. }
  449. // ConvertNotificationToXml converts BucketNotification value to XML data and returns it
  450. func ConvertNotificationToXml(input BucketNotification, returnMd5 bool, isObs bool) (data string, md5 string) {
  451. xml := make([]string, 0, 2+len(input.TopicConfigurations)*6)
  452. xml = append(xml, "<NotificationConfiguration>")
  453. for _, topicConfiguration := range input.TopicConfigurations {
  454. ret := converntConfigureToXML(topicConfiguration, "<TopicConfiguration>", isObs)
  455. xml = append(xml, ret)
  456. }
  457. xml = append(xml, "</NotificationConfiguration>")
  458. data = strings.Join(xml, "")
  459. if returnMd5 {
  460. md5 = Base64Md5([]byte(data))
  461. }
  462. return
  463. }
  464. // ConvertCompleteMultipartUploadInputToXml converts CompleteMultipartUploadInput value to XML data and returns it
  465. func ConvertCompleteMultipartUploadInputToXml(input CompleteMultipartUploadInput, returnMd5 bool) (data string, md5 string) {
  466. xml := make([]string, 0, 2+len(input.Parts)*4)
  467. xml = append(xml, "<CompleteMultipartUpload>")
  468. for _, part := range input.Parts {
  469. xml = append(xml, "<Part>")
  470. xml = append(xml, fmt.Sprintf("<PartNumber>%d</PartNumber>", part.PartNumber))
  471. xml = append(xml, fmt.Sprintf("<ETag>%s</ETag>", part.ETag))
  472. xml = append(xml, "</Part>")
  473. }
  474. xml = append(xml, "</CompleteMultipartUpload>")
  475. data = strings.Join(xml, "")
  476. if returnMd5 {
  477. md5 = Base64Md5([]byte(data))
  478. }
  479. return
  480. }
  481. func parseSseHeader(responseHeaders map[string][]string) (sseHeader ISseHeader) {
  482. if ret, ok := responseHeaders[HEADER_SSEC_ENCRYPTION]; ok {
  483. sseCHeader := SseCHeader{Encryption: ret[0]}
  484. if ret, ok = responseHeaders[HEADER_SSEC_KEY_MD5]; ok {
  485. sseCHeader.KeyMD5 = ret[0]
  486. }
  487. sseHeader = sseCHeader
  488. } else if ret, ok := responseHeaders[HEADER_SSEKMS_ENCRYPTION]; ok {
  489. sseKmsHeader := SseKmsHeader{Encryption: ret[0]}
  490. if ret, ok = responseHeaders[HEADER_SSEKMS_KEY]; ok {
  491. sseKmsHeader.Key = ret[0]
  492. } else if ret, ok = responseHeaders[HEADER_SSEKMS_ENCRYPT_KEY_OBS]; ok {
  493. sseKmsHeader.Key = ret[0]
  494. }
  495. sseHeader = sseKmsHeader
  496. }
  497. return
  498. }
  499. func parseCorsHeader(output BaseModel) (AllowOrigin, AllowHeader, AllowMethod, ExposeHeader string, MaxAgeSeconds int) {
  500. if ret, ok := output.ResponseHeaders[HEADER_ACCESS_CONRTOL_ALLOW_ORIGIN]; ok {
  501. AllowOrigin = ret[0]
  502. }
  503. if ret, ok := output.ResponseHeaders[HEADER_ACCESS_CONRTOL_ALLOW_HEADERS]; ok {
  504. AllowHeader = ret[0]
  505. }
  506. if ret, ok := output.ResponseHeaders[HEADER_ACCESS_CONRTOL_MAX_AGE]; ok {
  507. MaxAgeSeconds = StringToInt(ret[0], 0)
  508. }
  509. if ret, ok := output.ResponseHeaders[HEADER_ACCESS_CONRTOL_ALLOW_METHODS]; ok {
  510. AllowMethod = ret[0]
  511. }
  512. if ret, ok := output.ResponseHeaders[HEADER_ACCESS_CONRTOL_EXPOSE_HEADERS]; ok {
  513. ExposeHeader = ret[0]
  514. }
  515. return
  516. }
  517. func parseUnCommonHeader(output *GetObjectMetadataOutput) {
  518. if ret, ok := output.ResponseHeaders[HEADER_VERSION_ID]; ok {
  519. output.VersionId = ret[0]
  520. }
  521. if ret, ok := output.ResponseHeaders[HEADER_WEBSITE_REDIRECT_LOCATION]; ok {
  522. output.WebsiteRedirectLocation = ret[0]
  523. }
  524. if ret, ok := output.ResponseHeaders[HEADER_EXPIRATION]; ok {
  525. output.Expiration = ret[0]
  526. }
  527. if ret, ok := output.ResponseHeaders[HEADER_RESTORE]; ok {
  528. output.Restore = ret[0]
  529. }
  530. if ret, ok := output.ResponseHeaders[HEADER_OBJECT_TYPE]; ok {
  531. output.ObjectType = ret[0]
  532. }
  533. if ret, ok := output.ResponseHeaders[HEADER_NEXT_APPEND_POSITION]; ok {
  534. output.NextAppendPosition = ret[0]
  535. }
  536. }
  537. // ParseGetObjectMetadataOutput sets GetObjectMetadataOutput field values with response headers
  538. func ParseGetObjectMetadataOutput(output *GetObjectMetadataOutput) {
  539. output.AllowOrigin, output.AllowHeader, output.AllowMethod, output.ExposeHeader, output.MaxAgeSeconds = parseCorsHeader(output.BaseModel)
  540. parseUnCommonHeader(output)
  541. if ret, ok := output.ResponseHeaders[HEADER_STORAGE_CLASS2]; ok {
  542. output.StorageClass = ParseStringToStorageClassType(ret[0])
  543. }
  544. if ret, ok := output.ResponseHeaders[HEADER_ETAG]; ok {
  545. output.ETag = ret[0]
  546. }
  547. if ret, ok := output.ResponseHeaders[HEADER_CONTENT_TYPE]; ok {
  548. output.ContentType = ret[0]
  549. }
  550. output.SseHeader = parseSseHeader(output.ResponseHeaders)
  551. if ret, ok := output.ResponseHeaders[HEADER_LASTMODIFIED]; ok {
  552. ret, err := time.Parse(time.RFC1123, ret[0])
  553. if err == nil {
  554. output.LastModified = ret
  555. }
  556. }
  557. if ret, ok := output.ResponseHeaders[HEADER_CONTENT_LENGTH]; ok {
  558. output.ContentLength = StringToInt64(ret[0], 0)
  559. }
  560. output.Metadata = make(map[string]string)
  561. for key, value := range output.ResponseHeaders {
  562. if strings.HasPrefix(key, PREFIX_META) {
  563. _key := key[len(PREFIX_META):]
  564. output.ResponseHeaders[_key] = value
  565. output.Metadata[_key] = value[0]
  566. delete(output.ResponseHeaders, key)
  567. }
  568. }
  569. }
  570. // ParseCopyObjectOutput sets CopyObjectOutput field values with response headers
  571. func ParseCopyObjectOutput(output *CopyObjectOutput) {
  572. if ret, ok := output.ResponseHeaders[HEADER_VERSION_ID]; ok {
  573. output.VersionId = ret[0]
  574. }
  575. output.SseHeader = parseSseHeader(output.ResponseHeaders)
  576. if ret, ok := output.ResponseHeaders[HEADER_COPY_SOURCE_VERSION_ID]; ok {
  577. output.CopySourceVersionId = ret[0]
  578. }
  579. }
  580. // ParsePutObjectOutput sets PutObjectOutput field values with response headers
  581. func ParsePutObjectOutput(output *PutObjectOutput) {
  582. if ret, ok := output.ResponseHeaders[HEADER_VERSION_ID]; ok {
  583. output.VersionId = ret[0]
  584. }
  585. output.SseHeader = parseSseHeader(output.ResponseHeaders)
  586. if ret, ok := output.ResponseHeaders[HEADER_STORAGE_CLASS2]; ok {
  587. output.StorageClass = ParseStringToStorageClassType(ret[0])
  588. }
  589. if ret, ok := output.ResponseHeaders[HEADER_ETAG]; ok {
  590. output.ETag = ret[0]
  591. }
  592. }
  593. // ParseInitiateMultipartUploadOutput sets InitiateMultipartUploadOutput field values with response headers
  594. func ParseInitiateMultipartUploadOutput(output *InitiateMultipartUploadOutput) {
  595. output.SseHeader = parseSseHeader(output.ResponseHeaders)
  596. }
  597. // ParseUploadPartOutput sets UploadPartOutput field values with response headers
  598. func ParseUploadPartOutput(output *UploadPartOutput) {
  599. output.SseHeader = parseSseHeader(output.ResponseHeaders)
  600. if ret, ok := output.ResponseHeaders[HEADER_ETAG]; ok {
  601. output.ETag = ret[0]
  602. }
  603. }
  604. // ParseCompleteMultipartUploadOutput sets CompleteMultipartUploadOutput field values with response headers
  605. func ParseCompleteMultipartUploadOutput(output *CompleteMultipartUploadOutput) {
  606. output.SseHeader = parseSseHeader(output.ResponseHeaders)
  607. if ret, ok := output.ResponseHeaders[HEADER_VERSION_ID]; ok {
  608. output.VersionId = ret[0]
  609. }
  610. }
  611. // ParseCopyPartOutput sets CopyPartOutput field values with response headers
  612. func ParseCopyPartOutput(output *CopyPartOutput) {
  613. output.SseHeader = parseSseHeader(output.ResponseHeaders)
  614. }
  615. // ParseGetBucketMetadataOutput sets GetBucketMetadataOutput field values with response headers
  616. func ParseGetBucketMetadataOutput(output *GetBucketMetadataOutput) {
  617. output.AllowOrigin, output.AllowHeader, output.AllowMethod, output.ExposeHeader, output.MaxAgeSeconds = parseCorsHeader(output.BaseModel)
  618. if ret, ok := output.ResponseHeaders[HEADER_STORAGE_CLASS]; ok {
  619. output.StorageClass = ParseStringToStorageClassType(ret[0])
  620. } else if ret, ok := output.ResponseHeaders[HEADER_STORAGE_CLASS2]; ok {
  621. output.StorageClass = ParseStringToStorageClassType(ret[0])
  622. }
  623. if ret, ok := output.ResponseHeaders[HEADER_VERSION_OBS]; ok {
  624. output.Version = ret[0]
  625. }
  626. if ret, ok := output.ResponseHeaders[HEADER_BUCKET_REGION]; ok {
  627. output.Location = ret[0]
  628. } else if ret, ok := output.ResponseHeaders[HEADER_BUCKET_LOCATION_OBS]; ok {
  629. output.Location = ret[0]
  630. }
  631. if ret, ok := output.ResponseHeaders[HEADER_EPID_HEADERS]; ok {
  632. output.Epid = ret[0]
  633. }
  634. }
  635. func parseContentHeader(output *SetObjectMetadataOutput) {
  636. if ret, ok := output.ResponseHeaders[HEADER_CONTENT_DISPOSITION]; ok {
  637. output.ContentDisposition = ret[0]
  638. }
  639. if ret, ok := output.ResponseHeaders[HEADER_CONTENT_ENCODING]; ok {
  640. output.ContentEncoding = ret[0]
  641. }
  642. if ret, ok := output.ResponseHeaders[HEADER_CONTENT_LANGUAGE]; ok {
  643. output.ContentLanguage = ret[0]
  644. }
  645. if ret, ok := output.ResponseHeaders[HEADER_CONTENT_TYPE]; ok {
  646. output.ContentType = ret[0]
  647. }
  648. }
  649. // ParseSetObjectMetadataOutput sets SetObjectMetadataOutput field values with response headers
  650. func ParseSetObjectMetadataOutput(output *SetObjectMetadataOutput) {
  651. if ret, ok := output.ResponseHeaders[HEADER_STORAGE_CLASS]; ok {
  652. output.StorageClass = ParseStringToStorageClassType(ret[0])
  653. } else if ret, ok := output.ResponseHeaders[HEADER_STORAGE_CLASS2]; ok {
  654. output.StorageClass = ParseStringToStorageClassType(ret[0])
  655. }
  656. if ret, ok := output.ResponseHeaders[HEADER_METADATA_DIRECTIVE]; ok {
  657. output.MetadataDirective = MetadataDirectiveType(ret[0])
  658. }
  659. if ret, ok := output.ResponseHeaders[HEADER_CACHE_CONTROL]; ok {
  660. output.CacheControl = ret[0]
  661. }
  662. parseContentHeader(output)
  663. if ret, ok := output.ResponseHeaders[HEADER_EXPIRES]; ok {
  664. output.Expires = ret[0]
  665. }
  666. if ret, ok := output.ResponseHeaders[HEADER_WEBSITE_REDIRECT_LOCATION]; ok {
  667. output.WebsiteRedirectLocation = ret[0]
  668. }
  669. output.Metadata = make(map[string]string)
  670. for key, value := range output.ResponseHeaders {
  671. if strings.HasPrefix(key, PREFIX_META) {
  672. _key := key[len(PREFIX_META):]
  673. output.ResponseHeaders[_key] = value
  674. output.Metadata[_key] = value[0]
  675. delete(output.ResponseHeaders, key)
  676. }
  677. }
  678. }
  679. // ParseDeleteObjectOutput sets DeleteObjectOutput field values with response headers
  680. func ParseDeleteObjectOutput(output *DeleteObjectOutput) {
  681. if versionID, ok := output.ResponseHeaders[HEADER_VERSION_ID]; ok {
  682. output.VersionId = versionID[0]
  683. }
  684. if deleteMarker, ok := output.ResponseHeaders[HEADER_DELETE_MARKER]; ok {
  685. output.DeleteMarker = deleteMarker[0] == "true"
  686. }
  687. }
  688. // ParseGetObjectOutput sets GetObjectOutput field values with response headers
  689. func ParseGetObjectOutput(output *GetObjectOutput) {
  690. ParseGetObjectMetadataOutput(&output.GetObjectMetadataOutput)
  691. if ret, ok := output.ResponseHeaders[HEADER_DELETE_MARKER]; ok {
  692. output.DeleteMarker = ret[0] == "true"
  693. }
  694. if ret, ok := output.ResponseHeaders[HEADER_CACHE_CONTROL]; ok {
  695. output.CacheControl = ret[0]
  696. }
  697. if ret, ok := output.ResponseHeaders[HEADER_CONTENT_DISPOSITION]; ok {
  698. output.ContentDisposition = ret[0]
  699. }
  700. if ret, ok := output.ResponseHeaders[HEADER_CONTENT_ENCODING]; ok {
  701. output.ContentEncoding = ret[0]
  702. }
  703. if ret, ok := output.ResponseHeaders[HEADER_CONTENT_LANGUAGE]; ok {
  704. output.ContentLanguage = ret[0]
  705. }
  706. if ret, ok := output.ResponseHeaders[HEADER_EXPIRES]; ok {
  707. output.Expires = ret[0]
  708. }
  709. }
  710. // ConvertRequestToIoReaderV2 converts req to XML data
  711. func ConvertRequestToIoReaderV2(req interface{}) (io.Reader, string, error) {
  712. data, err := TransToXml(req)
  713. if err == nil {
  714. if isDebugLogEnabled() {
  715. doLog(LEVEL_DEBUG, "Do http request with data: %s", string(data))
  716. }
  717. return bytes.NewReader(data), Base64Md5(data), nil
  718. }
  719. return nil, "", err
  720. }
  721. // ConvertRequestToIoReader converts req to XML data
  722. func ConvertRequestToIoReader(req interface{}) (io.Reader, error) {
  723. body, err := TransToXml(req)
  724. if err == nil {
  725. if isDebugLogEnabled() {
  726. doLog(LEVEL_DEBUG, "Do http request with data: %s", string(body))
  727. }
  728. return bytes.NewReader(body), nil
  729. }
  730. return nil, err
  731. }
  732. // ParseResponseToBaseModel gets response from OBS
  733. func ParseResponseToBaseModel(resp *http.Response, baseModel IBaseModel, xmlResult bool, isObs bool) (err error) {
  734. readCloser, ok := baseModel.(IReadCloser)
  735. if !ok {
  736. defer func() {
  737. errMsg := resp.Body.Close()
  738. if errMsg != nil {
  739. doLog(LEVEL_WARN, "Failed to close response body")
  740. }
  741. }()
  742. body, err := ioutil.ReadAll(resp.Body)
  743. if err == nil && len(body) > 0 {
  744. if xmlResult {
  745. err = ParseXml(body, baseModel)
  746. } else {
  747. s := reflect.TypeOf(baseModel).Elem()
  748. if reflect.TypeOf(baseModel).Elem().Name() == "GetBucketPolicyOutput" {
  749. for i := 0; i < s.NumField(); i++ {
  750. if s.Field(i).Tag == "json:\"body\"" {
  751. reflect.ValueOf(baseModel).Elem().FieldByName(s.Field(i).Name).SetString(string(body))
  752. break
  753. }
  754. }
  755. } else {
  756. err = parseJSON(body, baseModel)
  757. }
  758. }
  759. if err != nil {
  760. doLog(LEVEL_ERROR, "Unmarshal error: %v", err)
  761. }
  762. }
  763. } else {
  764. readCloser.setReadCloser(resp.Body)
  765. }
  766. baseModel.setStatusCode(resp.StatusCode)
  767. responseHeaders := cleanHeaderPrefix(resp.Header)
  768. baseModel.setResponseHeaders(responseHeaders)
  769. if values, ok := responseHeaders[HEADER_REQUEST_ID]; ok {
  770. baseModel.setRequestID(values[0])
  771. }
  772. return
  773. }
  774. // ParseResponseToObsError gets obsError from OBS
  775. func ParseResponseToObsError(resp *http.Response, isObs bool) error {
  776. isJson := false
  777. if contentType, ok := resp.Header[HEADER_CONTENT_TYPE_CAML]; ok {
  778. jsonType, _ := mimeTypes["json"]
  779. isJson = contentType[0] == jsonType
  780. }
  781. obsError := ObsError{}
  782. respError := ParseResponseToBaseModel(resp, &obsError, !isJson, isObs)
  783. if respError != nil {
  784. doLog(LEVEL_WARN, "Parse response to BaseModel with error: %v", respError)
  785. }
  786. obsError.Status = resp.Status
  787. return obsError
  788. }
  789. // convertFetchPolicyToJSON converts SetBucketFetchPolicyInput into json format
  790. func convertFetchPolicyToJSON(input SetBucketFetchPolicyInput) (data string, err error) {
  791. fetch := map[string]SetBucketFetchPolicyInput{"fetch": input}
  792. json, err := json.Marshal(fetch)
  793. if err != nil {
  794. return "", err
  795. }
  796. data = string(json)
  797. return
  798. }
  799. // convertFetchJobToJSON converts SetBucketFetchJobInput into json format
  800. func convertFetchJobToJSON(input SetBucketFetchJobInput) (data string, err error) {
  801. objectHeaders := make(map[string]string)
  802. for key, value := range input.ObjectHeaders {
  803. if value != "" {
  804. _key := strings.ToLower(key)
  805. if !strings.HasPrefix(key, HEADER_PREFIX_OBS) {
  806. _key = HEADER_PREFIX_META_OBS + _key
  807. }
  808. objectHeaders[_key] = value
  809. }
  810. }
  811. input.ObjectHeaders = objectHeaders
  812. json, err := json.Marshal(input)
  813. if err != nil {
  814. return "", err
  815. }
  816. data = string(json)
  817. return
  818. }