向我的开发人员致意,
已经有3天我正在努力与Cosmos DB连接而没有成功。
我正在使用retrofit作为我的REST客户端,使用GsonConverterFactory进行序列化/反序列化。
当前状态是我从Cosmos DB REST API获取HTTP:400(错误请求)。我试图从this SO answer
采用身份验证标头生成所以这是我的代码(此单元测试可以从您的开发环境中运行。请参阅gradle.build
行以在本文的底部运行它:)
@RunWith(AndroidJUnit4.class)
@MediumTest
public class AzureDbConnectionTests {
public static final int COSMOS_PORT_NUM = 443;
public static final String COSMOS_DB_URL = "https://mazedb.documents.azure.com";
public static final String CONNECTION_STR =
COSMOS_DB_URL + ":" + COSMOS_PORT_NUM;
public static final String PRIMARY_KEY =
"<Private Key>";
// Entity to serialize into Cosmos DB
public static class Building {
public Building() {}
private String mName;
private String mAddress;
private String id;
}
public interface FirstAzureService {
@POST("/dbs/mazedb/colls/buildings/docs")
Call<Building> addDocument(
@Header("authorization") String authorization,
@Header("x-ms-date") String date,
@Body Building building);
}
@Test
public void serverConnectionTest() throws Exception {
String headerDate = getDateString();
Building building = new Building();
building.mName = "UUID";
building.id = UUID.randomUUID().toString();
Retrofit retrofit = new Retrofit.Builder().baseUrl(CONNECTION_STR)
.addConverterFactory(GsonConverterFactory.create()).build();
FirstAzureService azureService = retrofit.create(FirstAzureService.class);
Call<Building> buildingCall = azureService.addDocument(
generateAuthHeader("post", "docs", "dbs/mazedb/colls/buildings",
headerDate, PRIMARY_KEY), headerDate, building);
Response<Building> response = buildingCall.execute();
Log.d("AzureDbConnectionTest", "HTTP status code: " + response.code());
Log.d("AzureDbConnectionTest", "HTTP message: " + response.message());
Log.d("AzureDbConnectionTest", headerDate);
assertTrue(response.isSuccessful());
}
private String generateAuthHeader(String verb, String resourceType, String resourceId, String headerDate, String masterKeyBase64) throws Exception
{
//Decode the master key, and setup the MAC object for signing.
byte[] masterKeyBytes = Base64.decode(PRIMARY_KEY, Base64.NO_WRAP);
Mac mac = Mac.getInstance("HMACSHA256");
mac.init(new SecretKeySpec(masterKeyBytes, "HMACSHA256"));
//Build the unsigned auth string.
String stringToSign = verb.toLowerCase() + "\n"
+ resourceType.toLowerCase() + "\n"
+ resourceId.toLowerCase() + "\n"
+ headerDate.toLowerCase() + "\n"
+ "\n";
//Sign and encode the auth string.
String signature = Base64.encodeToString(
mac.doFinal(stringToSign.toLowerCase().getBytes("UTF8")), Base64.NO_WRAP);
//Generate the auth header.
String authHeader =
URLEncoder.encode("type=master&ver=1.0&sig=" + signature, "UTF8");
return authHeader;
}
@NonNull
public static String getDateString() {
SimpleDateFormat formatter =
new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
formatter.setTimeZone(TimeZone.getTimeZone("GMT"));
return formatter.format(new Date()).toLowerCase();
}
}
API是SQL API。 Azure Dashboard上显示的数据库数据: db structure
我还尝试为Android找到一些可用的Cosmos DB客户端,以节省时间摆弄身份验证和其余部分。但只能找到这个:https://github.com/Azure/Azure.Android。这正是我正在寻找的,但它仍处于开发阶段,并且缺少MongoDB API(我认为如果它会出现,我会使用MongoDB API来更容易切换)。
非常感谢您的帮助!我对此感到厌倦。
P.S。可以找到Azure Cosmos DB的HTTP状态代码列表on official website。从那里开始,代码400的原因是:
我认为最有可能是错误的JSON,但是在另一个单元测试中对同一个对象进行序列化之后我发现它没问题: { “ID”: “cceb3f5d-8d9c-44cd-85ee-599cd2f58783”, “MNAME”: “UUID”}
最基本的问候,格雷格。
build.gradle
来运行它:
dependencies {
androidTestCompile "junit:junit:4.12"
androidTestCompile "com.android.support:support-annotations:25.3.1"
androidTestCompile "com.android.support.test:runner:0.5"
androidTestCompile "com.android.support.test:rules:0.5"
androidTestCompile "com.google.code.gson:gson:2.8.2"
androidTestCompile "com.squareup.retrofit2:retrofit:2.4.0"
androidTestCompile "com.squareup.retrofit2:converter-gson:2.4.0"
}
答案 0 :(得分:1)
使用generateAuthHeader
方法提供dbs/mazedb/colls/buildings
作为集合ID的String resourceId
。
这是错误的。
您应该将其更改为buildings
。