2011-12-12 3 views
3

J'essaie de télécharger un appel d'échange de données en masse vers eBay en utilisant leur API FileTransfer. Pour ce faire, je dois POSTER une chaîne de requête xml sur le serveur eBay mais la requête xml contient une section <Data> qui doit inclure les données que vous transférez (dans ce cas, il s'agit d'un fichier zip encodé en base64 contenant un autre document XML). eBay donne un exemple en C# de la façon de construire un tel document: https://ebay.custhelp.com/app/answers/detail/a_id/1561Requête HTTP POST et en-têtes avec pièces jointes MIME multipart/related et xop?

J'ai essayé de recréer cet exemple en python en utilisant httplib pour POST une chaîne que j'ai construite de la même manière que l'exemple (le 3 UUID sont uniques):

request = """ 
--MIMEBoundaryurn_uuid_{XMLUUID} 
    Content-Type: application/xop+xml;charset=UTF-8;type="text/xml;charset=UTF-8"; 
    Content-Transfer-Encoding: binary 
    Content-ID:<0.urn:uuid:{REQUUID}> 
    <?xml version="1.0" encoding="utf-8"?> 
    <uploadFileRequest xmlns:sct=\"http://www.ebay.com/soaframework/common/types\" xmlns="http://www.ebay.com/marketplace/services"> 
    <fileAttachment> 
     <Size>{Size}</Size> 
     <Data><xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" 
     href="cid:urn:uuid:{ATTCHMNTUUID}>"</Data> 
    </fileAttachment> 
    <fileFormat>{fileFormat}</fileFormat> 
    <fileReferenceId>{fileReferenceId}</fileReferenceId> 
    <taskReferenceId>{taskReferenceId}</taskReferenceId> 
    </uploadFileRequest> 
    --MIMEBoundaryurn_uuid_{XMLUUID} 
    Content-Type: application/octet-stream 
    Content-Transfer-Encoding: binary 
    Content-ID: <urn.uuid:{ATTCHMNTUUID}>\r\n 
    {Data} 
    --MIMEBoundaryurn_uuid_{XMLUUID}-- 
    """.replace("\t", "") 

request_dict = { 
    'Size': size, 
    'Data': payload, 
    'fileFormat': 'zip', 
    'fileReferenceId': '50000935383', 
    'taskReferenceId': '50000847753', 
    'REQUUID': reqUUID, 
    'XMLUUID': xmlUUID, 
    'ATTCHMNTUUID': attchmntUUID, 
} 


request = request.format(**request_dict) 

avec en-têtes qui ressemblent à ceci:

headers = { 
'X-EBAY-SOA-OPERATION-NAME': 'uploadFile', 
'X-EBAY-SOA-SERVICE-NAME': 'FileTransferService', 
'X-EBAY-SOA-SECURITY-TOKEN': #Auth Token, 
'Content-type': "multipart/related; boundary=" + boundary + ";type=\"application/xop+xml\";start=\"<0." + "urn:uuid:" + str(requuid) + ">\";start-info=\"text/xml\"" 
} 

puis mon POST:

connection = httplib.HTTPSConnection('storage.sandbox.ebay.com') 
connection.request("POST", '/FileTransferService', request, headers) 

Lorsque je publie la requête XML sans les informations de pièce jointe MIME, elle accepte le fichier sans problème. Mais quand j'essaye de le faire comme le code ci-dessus, avec des pièces jointes MIME multipart/liées et la balise <xop> indiquant où les données se trouvent dans la pièce jointe, le POST échoue et j'obtiens un "Erreur 302: déplacé temporairement" réponse. Cela me porte à croire que quelque chose ne va pas avec comment j'ai construit la requête MIME multipart/related xml, ou comment j'ai construit la déclaration d'en-tête "Content-type", ou mon utilisation de xop, ou probablement une combinaison des trois des choses.

Je suppose que ma question est: Comment puis-je créer une requête XML qui contient des sections MIME multipart/connexes et utilise également xop?

Merci pour l'aide!

Wes

Répondre

2

Je compris ce qui était mal à ma demande. C'est une combinaison de la construction de la chaîne de requête et des en-têtes. Je suis allé avec une approche beaucoup plus organisée et programmatique, et cela a fonctionné.

Voici ce que la section qui construit la chaîne de requête ressemble à:

########################################### 
# UUIDs 
########################################### 
reqUUID= uuid.uuid4() 
attchmntUUID = uuid.uuid4() 

########################################## 
# MIME strings 
########################################## 
URN_UUID_REQUEST = "<0.urn:uuid:%s>"% reqUUID 
URN_UUID_ATTACHMENT = "urn:uuid:%s" % attchmntUUID 
MIME_BOUNDARY = "MIME_boundary" 

request_dict = { 
    'Size': size, 
    'Data': payload, 
    'fileFormat': 'gzip', 
    'fileReferenceId': '50000945773', 
    'taskReferenceId': '50000858033', 
    'REQUUID': reqUUID, 
    'ATTCHMNTUUID': attchmntUUID, 
} 


def build_request(request_dict): 
    ''' 
    Build the request string with MIME Attachment 
    ''' 

    request = '<uploadFileRequest xmlns:sct="http://www.ebay.com/soaframework/common/types" xmlns="http://www.ebay.com/marketplace/services">\r\n' 
    request += '<taskReferenceId>%s</taskReferenceId>\r\n' % request_dict['taskReferenceId'] 
    request += '<fileReferenceId>%s</fileReferenceId>\r\n' % request_dict['fileReferenceId'] 
    request += '<fileFormat>%s</fileFormat>\r\n' % request_dict['fileFormat'] 
    request += '<fileAttachment>\r\n' 
    request += '<Size>%s</Size>\r\n'% request_dict['Size'] 
    request += '<Data><xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:%s"/></Data>\r\n'%URN_UUID_ATTACHMENT 
    request += '</fileAttachment>\r\n' 
    request += '</uploadFileRequest>\r\n' 

    return request 


def build_mime_message(request, data): 
    ''' 
    Build the xml string with MIME attachments and the base64 encoded data string 
    ''' 

    request_part = '\r\n' 
    request_part += '--%s\r\n' % MIME_BOUNDARY 
    request_part += 'Content-Type: application/xop+xml; charset=UTF-8; type="text/xml; charset=UTF-8"\r\n' 
    request_part += 'Content-Transfer_Encoding: binary\r\n' 
    request_part += 'Content-ID: %s\r\n\r\n' % URN_UUID_REQUEST 
    request_part += '%s\r\n' % request 


    binary_part = '\r\n' 
    binary_part += '--%s\r\n' % MIME_BOUNDARY 
    binary_part += 'Content-Type: application/octet-stream\r\n' 
    binary_part += 'Content-Transfer-Encoding: base64\r\n' 
    binary_part += 'Content-ID: <%s>\r\n\r\n' % URN_UUID_ATTACHMENT 
    binary_part += '%s\r\n' % data 
    binary_part += '--%s--' % MIME_BOUNDARY 

    return request_part + binary_part 

request = build_request(request_dict) 
request = build_mime_message(request, data)#data is base64 encoded gzip compressed xml file 

Et les en-têtes ressemblent à ceci:

content_type_string = 'multipart/related;' 
content_type_string += ' boundary=%s;' % MIME_BOUNDARY 
content_type_string += ' type="application/xop+xml";' 
content_type_string += ' start="%s";' % URN_UUID_REQUEST 
content_type_string += ' start-info="text/xml"' 

headers = { 
'X-EBAY-SOA-OPERATION-NAME': 'uploadFile', 
'X-EBAY-SOA-SERVICE-NAME': 'FileTransferService', 
'X-EBAY-SOA-SECURITY-TOKEN': #auth token, 
'Content-Length': len(request), 
'Content-Type': content_type_string 
} 

donc de tout cela, je réunis que le problème était avec les nouvelles lignes et les caractères de tabulation dans l'en-tête et la demande.

+0

J'essaie d'adopter moi-même cette réponse pour utiliser l'appel uploadFile. Je continue d'obtenir un "Veuillez spécifier un fichier avec un format valide". Je génère le XML dans la mémoire, puis gzipping et le mettre en base64 avec base64.standard_b64encode (gzip.compress (full_xml)) – Nelluk

Questions connexes