skip to Main Content

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.

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;

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:

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;

which gives error: 401 unauthorized

2

Answers


  1. Chosen as BEST ANSWER

    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:

    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;
        }
      }
    }

    and in my "scripts" in package.json., replaced react-scripts start to craco start as below:

    "start": "craco start",
    "build": "craco build",

    in my getServiceTopicMessage.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;

    and just import the function in your required page and call. it works


  2. 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

    enter image description here

    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.

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search