英文:
How to get notification from azure service bus topic from frontend?
问题
我们正在使用 Azure 服务总线进行通知服务。在 Azure 门户中,已创建服务总线主题并在主题中可用消息。我正尝试使用 REST API 服务获取主题数据。
这是我目前拥有的代码。
import axios from 'axios';
const namespace = 'my-namespace';
const topicName = 'my-topic-name';
const subscriptionId = 'my-subscription-id';
const accesskey = 'my-access-key';
const baseurl = `https://${namespace}.servicebus.windoes.net`;
const url = `${baseurl}/${topicName}/subscriptions/${subscriptionId}`;
const headers = {
Authorization: `SharedAccessSignature ${accesskey}`,
'content-type': 'application/json',
}
const getDetails = async () => {
try {
const response = await axios.get(url, { headers });
console.log('response', response.data);
} catch (error) {
console.error('error', error);
}
}
export default getDetails;
我目前对前端所需的内容了解有限。我尝试使用 @azure/service-bus
,但出现了 cant resolve 'os' in rhea,webpack < 5 used
错误。
因此,我尝试消除依赖关系并使用 https
服务。
我目前遇到 401 未经授权
错误。您能指导我在哪里出错了吗?
根据建议更新的代码:
import axios from 'axios';
import { SHA256 } from 'crypto-js';
const sbName = 'my-sb-name';
const topicName = 'my-topic-name';
const sharedAccessKey = 'my-shared-access-key';
const sharedAccessName = 'RootManagerSharedAccessKey';
const expiry = Math.floor(Date.now() / 1000) + 10000;
const baseUrl = `https://${sbName}.servicebus.windows.net`;
const url = `${baseUrl}/${topicName}`;
const toSign = `${url}\n${expiry.toString()}`;
const signature = SHA256(toSign).toString();
const encodedSignature = encodeURIComponent(signature);
const authFormat = `SharedAccessSignature sig={0}&se={1}&skn={2}&sr={3}`;
const auth = authFormat
.replace('{0}', encodedSignature)
.replace('{1}', expiry.toString())
.replace('{2}', sharedAccessName)
.replace('{3}', url);
console.log(auth);
const headers = {
Authorization: auth,
'Content-Type': 'application/json',
};
const getDetails = async () => {
try {
const response = await axios.get(url, { headers });
console.log('Queue Details:', response.data);
// 处理响应或使用检索到的队列详情更新 UI
} catch (error) {
console.error('Error retrieving queue details:', error);
}
};
// 调用函数以获取队列详情
export default getDetails;
这会产生错误:401 未经授权
。
英文:
we are using azure-service-bus for notification services. in azure portal., service bus topic has been created and message is available in topic. Iam trying to use REST API services to get the topic data.
This is the code I have currently.
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
import axios from 'axios';
const namespace = 'my-namespace';
const topicName = 'my-topic-name';
const subscriptionId = 'my-subscription-id';
const accesskey = 'my-access-key';
const baseurl = `https://${namespace}.servicebus.windoes.net`;
const url = `${baseurl}/${topicName}/subscriptions/${subscriptionId}`;
const headers = {
Authorization: `SharedAccessSignature ${accesskey}`,
'content-type': 'application/json',
}
const getDetails = async () => {
try {
const response = await axios.get(url, { headers });
console.log('response', response.data);
} catch (error) {
console.error('error', error);
}
}
export default getDetails;
<!-- end snippet -->
I currently have very limited understanding on what is required in frontend. I was trying to use @azure/service-bus
., but it is giving error cant resolve 'os' in rhea., webpack < 5 used
error.
Hence I tried to eliminate the dependency and used https
services.
iam currentlu getting 401 unauthorized
error.
can you guide me where iam doing wrong?
updated code as per suggestions:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
import axios from 'axios';
import { SHA256 } from 'crypto-js';
const sbName = 'my-sb-name';
const topicName = 'my-topic-name';
const sharedAccessKey = 'my-shared-access-key';
const sharedAccessName = 'RootManagerSharedAccessKey';
const expiry = Math.floor(Date.now() / 1000) + 10000;
const baseUrl = `https://${sbName}.servicebus.windows.net`;
const url = `${baseUrl}/${topicName}`;
const toSign = `${url}\n${expiry.toString()}`;
const signature = SHA256(toSign).toString();
const encodedSignature = encodeURIComponent(signature);
const authFormat = `SharedAccessSignature sig={0}&se={1}&skn={2}$sr={3}`;
const auth = authFormat
.replace('{0}', encodedSignature)
.replace('{1}', expiry.toString())
.replace('{2}', sharedAccessName)
.replace('{3}', url);
console.log(auth);
const headers = {
Authorization: auth,
'Content-Type': 'application/json',
};
const getDetails = async () => {
try {
const response = await axios.get(url, { headers });
console.log('Queue Details:', response.data);
// Process the response or update your UI with the retrieved queue details
} catch (error) {
console.error('Error retrieving queue details:', error);
}
};
// Call the function to get queue details
export default getDetails;
<!-- end snippet -->
which gives error: 401 unauthorized
答案1
得分: 1
> 我目前遇到了401未经授权
的错误
这是因为您提供了不正确的授权密钥。
您可以使用以下代码生成SAS令牌,然后将其用于Authorization头部以获取主题数据。
生成SAS令牌的代码
const crypto = require('crypto');
const querystring = require('querystring');
const sb_name = 'afreen-serviceBus-01';
const topic = 'demotopic';
const url = `https://${sb_name}.servicebus.windows.net/${topic}`;
const sas_value = 'xxxxxxxxxxx'; // 您的共享访问密钥
const sas_name = 'RootManageSharedAccessKey'; // 您的共享访问规则名称
const expiry = Math.floor(Date.now() / 1000) + 10000;
const to_sign = `${url}\n${expiry}`;
const signature = crypto.createHmac('sha256', sas_value)
.update(to_sign)
.digest('base64');
const encodedSignature = querystring.escape(signature);
const auth_format = 'SharedAccessSignature sig={0}&se={1}&skn={2}&sr={3}';
const auth = auth_format.replace('{0}', encodedSignature)
.replace('{1}', expiry)
.replace('{2}', sas_name)
.replace('{3}', url);
console.log(auth);
输出
请参考微软文档
在Authorization: SharedAccessSignature ${access key}
的位置使用上面生成的SharedAccessSignature密钥。
除了访问密钥之外,我使用了您的代码而没有进行任何修改。我使用了上面生成的密钥,得到了预期的结果。
英文:
> I am currently getting 401 unauthorized
error
It is because you are providing incorrect authorization key.
You can use the below code to generate the SAS token and then you can use it in the Authorization header to get the topic data.
Code to generate SAS token
const crypto = require('crypto');
const querystring = require('querystring');
const sb_name = 'afreen-serviceBus-01';
const topic = 'demotopic';
const url = `https://${sb_name}.servicebus.windows.net/${topic}`;
const sas_value = 'xxxxxxxxxxx'; // your shared access key
const sas_name = 'RootManageSharedAccessKey'; // your shared access rule name
const expiry = Math.floor(Date.now() / 1000) + 10000;
const to_sign = `${url}\n${expiry}`;
const signature = crypto.createHmac('sha256', sas_value)
.update(to_sign)
.digest('base64');
const encodedSignature = querystring.escape(signature);
const auth_format = 'SharedAccessSignature sig={0}&se={1}&skn={2}&sr={3}';
const auth = auth_format.replace('{0}', encodedSignature)
.replace('{1}', expiry)
.replace('{2}', sas_name)
.replace('{3}', url);
console.log(auth);
Output
Please refer ms docs
Use the above generated SharedAccessSignature key in the place of access key of Authorization: SharedAccessSignature ${access key}
.
I have used your code without any modification except the access key. I have used the above generated key which gave me the expected result.
答案2
得分: 0
我使用了 @azure/service-bus
并按照官方文档的建议配置了依赖项,它正常工作。
我在我的 react 18
应用中使用了 react-scripts
。因此,为了将推荐的配置与 react-scripts
合并,我将 @craco/craco
安装为开发依赖项。
在我的 craco.config.js
文件中添加了以下配置:
const webpack = require('webpack');
module.exports = {
webpack: {
configure: (webpackConfig) => {
webpackConfig.resolve.fallback = {
...webpackConfig.resolve.fallback,
os: require.resolve('os-browserify/browser'),
path: require.resolve('path-browserify'),
buffer: require.resolve('buffer/'),
process: require.resolve('process/browser'),
}
webpackConfig.plugins.push(
new webpack.ProvidePlugin({
Buffer: ['buffer', 'Buffer'],
process: 'process/browser'
})
);
return webpackConfig;
}
}
}
在我的 package.json
文件中的 "scripts" 部分,将 react-scripts start
替换为 craco start
:
"scripts": {
"start": "craco start",
"build": "craco build",
// ...
}
在我的 getServiceTopicMessage.js
文件中:
import { ServiceBusClient } from '@azure/service-bus';
async function getServiceBusTopicMessage() {
const connectionString = '你的连接字符串';
const topicName = '你的主题名称';
const subscriptionName = '你的订阅名称';
const serviceBusClient = new ServiceBusClient(connectionString);
const receiver = serviceBusClient.createReceiver(topicName, subscriptionName);
try {
console.log('等待消息...');
while(true) {
const messages = await receiver.receiveMessages(1, {maxWaitTimeInMs: 5000});
if(messages.length > 0) {
console.log(messages[0].body);
await receiver.completeMessage(messages[0]);
}
}
} catch (error) {
console.error(error);
} finally {
await receiver.close();
await serviceBusClient.close();
}
}
export default getServiceBusTopicMessage;
只需在所需的页面中导入该函数并调用,它就会正常工作。
英文:
I used @azure/service-bus
and configured the dependencies as suggested in their official documentaion and it worked.
Iam using react-scripts
for my react 18
app. So., inorder to merge the recommended config with react-scripts
., I installed @craco/craco
as dev dependency.
in my craco.config.js
added following configuration:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
const webpack = require('webpack');
module.exports = {
webpack: {
configure: (webpackConfig) => {
webpackConfig.resolve.fallback = {
...webpackConfig.resolve.fallback,
os: require.resolve('os-browserify/browser'),
path: require.resolve('path-browserify'),
buffer: require.resolve('buffer/'),
process: require.resolve('process/browser'),
}
webpackConfig.plugins.push(
new webpack.ProvidePlugin({
Buffer: ['buffer', 'Buffer'],
process: 'process/browser'
})
);
return webpackConfig;
}
}
}
<!-- end snippet -->
and in my "scripts" in package.json., replaced react-scripts start
to craco start
as below:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
"start": "craco start",
"build": "craco build",
<!-- end snippet -->
in my getServiceTopicMessage.js
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
import { ServiceBusClient } from '@azure/service-bus';
async function getServiceBusTopicMessage() {
const connectionString = 'your connection string';
const topicName = 'your topic name';
const subscriptionName = 'your subscription name';
const serviceBusClient = new ServiceBusClient(connectionString);
const receiver = serviceBusClient.createReceiver(topicName, subscriptionName);
try {
console.log('waiting for messages...');
while(true) {
const messages = await receiver.receiveMessages(1, {maxWaitTimeInMs: 5000});
if(messages.length > 0) {
console.log(messages[0].body);
await receiver.completeMessage(messages[0]);
}
}
} catch (error) {
console.error(error);
} finally {
await receiver.close();
await serviceBusClient.close();
}
}
export default getServiceBusTopicMessage;
<!-- end snippet -->
and just import the function in your required page and call. it works
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论